/* File: global_sum_div0.c * Purpose: Driver for MPI global sum function * Input: None * Output: Random values generated by processes and sum of these * values. * * Algorithm: * 1. Each process computes a random int x from 0 to MAX_CONTRIB-1 * 2. Processes call Global_sum function which sums the local * values on process 0 * 3. Process 0 prints global sum * * Compile: mpicc -g -Wall -o global_sum0 global_sum0.c * Run: mpiexec -n global_sum0 * * Notes: * 1. The number of processes should be a power of 2 * 2. This version uses modular arithmetic rather than bitmasks * 3. The value returned by global_sum on processes other * than 0 is meaningless. * 4. DEBUG flag can be used to print information on pairing * of processes. */ #include #include #include "mpi.h" #define MAX_CONTRIB 20 int Global_sum(int myContrib, int my_rank, int p, MPI_Comm comm); int main(void) { int p, my_rank; MPI_Comm comm; int x; int total; MPI_Init(NULL, NULL); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &my_rank); srandom(my_rank); x = random() % MAX_CONTRIB; printf("Proc %d > x = %d, p = %d\n", my_rank, x, p); total = Global_sum(x, my_rank, p, comm); if (my_rank == 0) printf("The total is %d\n", total); MPI_Finalize(); return 0; } /* main */ /*--------------------------------------------------------------- * Function: Global_sum * Purpose: Compute global sum of values distributed across * processes * Input args: * my_contrib: the calling process' contribution to the global sum * my_rank: the calling process' rank in the communicator * p: the number of processes in the communicator * comm: the communicator used for sends and receives * * Return val: the sum of the my_contrib values contributed by * each process. * * Algorithm: Use tree structured communication, pairing processes * to communicate. * * Notes: * 1. The value returned by global_sum on processes other * than 0 is meaningless. * 2. The pairing of the processes is done using modular * arithmetic. */ int Global_sum(int my_contrib, int my_rank, int p, MPI_Comm comm) { int sum = my_contrib; int temp; int divisor = 2; int proc_diff = 1; int partner; int done = 0; int i_send; # ifdef DEBUG int my_pass = -1; partner = -1; printf("Proc %d > partner = %d, pass = %d, p = %d, done = %d\n", my_rank, partner, my_pass, p, done); fflush(stdout); # endif while (!done && divisor <= p) { i_send = my_rank % divisor; if (i_send) { partner = my_rank - proc_diff; # ifdef DEBUG my_pass++; printf("Proc %d > partner = %d, pass = %d, i_send = %d, sum = %d\n", my_rank, partner, my_pass, i_send, sum); fflush(stdout); # endif MPI_Send(&sum, 1, MPI_INT, partner, 0, comm); done = 1; } else { /* I'm receiving */ partner = my_rank + proc_diff; # ifdef DEBUG my_pass++; printf("Proc %d > partner = %d, pass = %d, i_send = %d \n", my_rank, partner, my_pass, i_send); fflush(stdout); # endif MPI_Recv(&temp, 1, MPI_INT, partner, 0, comm, MPI_STATUS_IGNORE); sum += temp; # ifdef DEBUG printf("Proc %d > partner = %d, pass = %d, received = %d, sum = %d\n", my_rank, partner, my_pass, temp, sum); fflush(stdout); # endif divisor *= 2; proc_diff *= 2; } } /* Valid only on 0 */ return sum; } /* Global_sum */