Bu Blogda Ara

7 Şubat 2010 Pazar

functions for determining whether every process has exhausted its stack

/* terminate.c -- functions for determining whether every process has
* exhausted its stack.
*
* Here's the basic idea. At the start of the program, process 0 has
* one unit of some indestructible quantity -- I called it energy.
* When the data is distributed, the energy is divided into p
* equal parts and also distributed among the processes. So each
* process has 1/p of the energy. (I don't actually send the energy
* out initially, since every process knows it will get 1/p units of
* energy, each can just set its energy to 1/p). Whenever
* a process exhausts its local stack, it sends whatever energy
* it has to process 0. Whenever a process satisfies a request
* for work, it splits its energy in two equal pieces, keeping half
* for itself and sending half to the process receiving the work.
* Each process keeps track of its available energy in "my_energy".
* Process 0, also keeps track of returned energy in "returned_energy."
* Since energy is never destroyed, the sum of all energy on all the
* processes will always be 1. When process 0 finds that
* "returned_energy" is 1, no process (including itself) will have
* any work left, and it can broadcast a termination message to all
* processes. The only catch here is that floating point
* arithmetic isn't exact. So there are functions for
* rational arithmetic: a fraction a/b is represented as a pair of
* longs (a,b). Dividing by 2 changes (a,b) to (a,2b). Adding
* (a,b) + (c,d) = (ad + bc,bd). This can still cause problems,
* but there are no security checks. Future work, no doubt.
*
* See Chap 14, pp. 334 & ff, in PPMPI.
*/
#include "mpi.h"
#include "node_stack.h"
#include
#include
#include "terminate.h"

MPI_Datatype rational_mpi_t;
extern int p;
extern int my_rank;

static DIVISOR_T divs;
static int prime_list[MAX_PRIMES] =
{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};

static RATIONAL_T ONE = {1,1};
static RATIONAL_T my_energy;
static RATIONAL_T returned_energy = {0,1}; /* significant only on proc 0 */



/*********************************************************************/
void Print_divisors(void) {
int i;
printf("Process %d > Divisors of %d are ", my_rank, 2*p);
for (i = 0; i < Num_divisors(divs); i++)
printf("%d ", Divisor(divs,i));
printf("\n");
} /* Print_divisors */


/*********************************************************************/
void Setup_term_detect(void) {

Find_divisors(2*p); /* Use 2*p to force inclusion of 2 in list */
/* of divisors */
my_energy.numerator = 1;
my_energy.denominator = p;

Build_rational_mpi_t();


} /* Setup_term_detect */


/*********************************************************************/
void Build_rational_mpi_t(void) {
int count = 2;
int block_lengths[2];
MPI_Datatype types[2];
MPI_Aint displacements[2];
MPI_Aint start;
MPI_Aint address;

block_lengths[0] = block_lengths[1] = 1;
types[0] = types[1] = MPI_LONG;

MPI_Address(&my_energy, &start);
MPI_Address(&(my_energy.numerator), &address);
displacements[0] = address - start;
MPI_Address(&(my_energy.denominator), &address);
displacements[1] = address - start;

MPI_Type_struct(count, block_lengths, displacements, types,
&rational_mpi_t);
MPI_Type_commit(&rational_mpi_t);
} /* Build_rational_mpi_t */


/*********************************************************************/
void Find_divisors(int x) {
int quotient = x;
int remainder;
int prime_indx = 0;
int divisor_indx = 0;
int prime;

while(quotient != 1) {
prime = prime_list[prime_indx];
remainder = quotient % prime;
if (remainder == 0) {
Divisor(divs,divisor_indx) = prime;
divisor_indx++;
do {
quotient = quotient/prime;
remainder = quotient % prime;
} while (remainder == 0);
}
prime_indx++;
if ((quotient != 1) && (prime_indx >= MAX_PRIMES)) {
Print_divisors();
fprintf(stderr, "x = %d has too many distinct divisors\n", x);
fprintf(stderr, "Increase the size of prime_list\n");
exit(-1);
}
}

Num_divisors(divs) = divisor_indx;

} /* Find_divisors */


/*********************************************************************/
void Reduce(RATIONAL_T* y) {
int i;
int divisor;

for (i = 0; i < Num_divisors(divs); i++) {
divisor = Divisor(divs,i);
while (((Numerator(y) % divisor) == 0) &&
(Denominator(y) % divisor) == 0) {
Numerator(y) = Numerator(y)/divisor;
Denominator(y) = Denominator(y)/divisor;
}
}
} /* Reduce */


/*********************************************************************/
/* Add x = x + y */
void Add(RATIONAL_T* x, RATIONAL_T* y) {

Numerator(x) = Denominator(y)*Numerator(x) + Denominator(x)*Numerator(y);
Denominator(x) = Denominator(x)*Denominator(y);
Reduce(x);
} /* Add */


/*********************************************************************/
void Divide_by_2(
RATIONAL_T* x /* in/out */) {

if ((Numerator(x) % 2) == 0)
Numerator(x) = Numerator(x)/2;
else
Denominator(x) = 2*Denominator(x);
} /* Divide_by_2 */


/*********************************************************************/
int Equal(RATIONAL_T* x, RATIONAL_T* y) {

if ( Numerator(x)*Denominator(y) ==
Numerator(y)*Denominator(x) )
return TRUE;
else
return FALSE;
} /* Equal */


/*********************************************************************/
void Send_half_energy(
int destination /* in */,
MPI_Comm comm /* in */) {

Divide_by_2(&my_energy);

MPI_Send(&my_energy, 1, rational_mpi_t, destination,
HALF_ENERGY_TAG, comm);
} /* Send_half_energy */


/*********************************************************************/
void Recv_half_energy(
int source /* in */,
MPI_Comm comm /* out */) {
MPI_Status status;

MPI_Recv(&my_energy, 1, rational_mpi_t, source,
HALF_ENERGY_TAG, comm, &status);
} /* Recv_half_energy */


/*********************************************************************/
void Return_energy(MPI_Comm comm) {

MPI_Send(&my_energy, 1, rational_mpi_t, 0, RETURN_ENERGY_TAG, comm);

} /* Return_energy */


/*********************************************************************/
void Receive_returned_energy(
MPI_Comm comm /* in */) {
int done = FALSE;
int source;
int energy_returned;
RATIONAL_T energy;
MPI_Status status;

while (!done) {
MPI_Iprobe(MPI_ANY_SOURCE, RETURN_ENERGY_TAG, comm,
&energy_returned, &status);
if (energy_returned) {
source = status.MPI_SOURCE;
MPI_Recv(&energy, 1, rational_mpi_t, source,
RETURN_ENERGY_TAG, comm, &status);
Add(&returned_energy, &energy);
} else {
done = TRUE;
}
} /* while */
} /* Receive_returned_energy */


/*********************************************************************/
int Search_complete(
MPI_Comm comm /* in */) {
int dest;
int x = 0;
int completed;
MPI_Status status;

if (my_rank == 0) {
Receive_returned_energy(comm);
if (Equal(&returned_energy, &ONE)) {
for (dest = 1; dest < p; dest++) {
MPI_Send(&x, 1, MPI_INT, dest, COMPLETE_TAG, comm);
}
return TRUE;
} else {
return FALSE;
}
} else { /* my_rank != 0 */
MPI_Iprobe(0, COMPLETE_TAG, comm, &completed, &status);
if (completed) {
MPI_Recv( &x, 1, MPI_INT, 0, COMPLETE_TAG, comm, &status);
return TRUE;
} else {
return FALSE;
}
}

} /* Search_complete */

Hiç yorum yok:

Yorum Gönder