/* File: global_sum_div.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_sum global_sum.c * Run: mpiexec -n global_sum * * Notes: * 1. This version has no restriction on the number of processes. * 2. This version uses modular arithmetic rather than bitmasks * 3. The value returned by global_sum on processes other * than 0 is meaningless. */ #include #include #include "mpi.h" #define MAX_CONTRIB 20 int Global_sum(int myContrib, int my_rank, int p, MPI_Comm comm); int Smallest_power_two(int p); 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, smallest-power-two = %d\n", my_rank, x, p, Smallest_power_two(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; while (!done && divisor <= Smallest_power_two(p)) { i_send = my_rank % divisor; if (i_send) { partner = my_rank - proc_diff; MPI_Send(&sum, 1, MPI_INT, partner, 0, comm); done = 1; } else { /* I'm receiving */ partner = my_rank + proc_diff; if (partner < p) { MPI_Recv(&temp, 1, MPI_INT, partner, 0, comm, MPI_STATUS_IGNORE); sum += temp; } divisor *= 2; proc_diff *= 2; } } /* Valid only on 0 */ return sum; } /* Global_sum */ int Smallest_power_two(int p) { int temp = 1; while (temp < p) temp *= 2; return temp; }