#include <stdio.h> #include <string.h> #include <sys/types.h> #include <math.h> #include <limits.h> #include "mpi.h" #define CHUNKSIZE 1000 #define REQUEST 1 #define REPLY 2 int main ( int argc, char **argv ) { int pool_size, my_rank, host_rank, destination, source, node_name_length, *host_rank_ptr, found_flag, int_buffer[BUFSIZ]; char char_buffer[BUFSIZ], my_node_name[BUFSIZ], console_name[BUFSIZ], host_name[BUFSIZ]; MPI_Status status; boolean_t i_am_the_master = B_FALSE; #include "preamble.c" { MPI_Comm world, workers; MPI_Group world_group, worker_group; int ranks[1], server, request, rands[CHUNKSIZE], done, in, out, max, my_worker_rank, iter, totalin, totalout, i; double x, y, epsilon, error, Pi; boolean_t i_am_the_server = B_FALSE; if (i_am_the_master) { printf ( "epsilon = " ); scanf ( "%lf", &epsilon ); } MPI_Bcast ( &epsilon, 1, MPI_DOUBLE, host_rank, MPI_COMM_WORLD ); world = MPI_COMM_WORLD; /* Server must not be the same process as the host. We must have sufficient number of processes so as not to hit a negative rank number here! */ server = (host_rank == pool_size - 1)? pool_size - 2 : pool_size - 1; if (my_rank == server) i_am_the_server = B_TRUE; MPI_Comm_group ( MPI_COMM_WORLD, &world_group ); ranks[0] = server; MPI_Group_excl ( world_group, 1, ranks, &worker_group ); MPI_Comm_create ( world, worker_group, &workers ); MPI_Group_free ( &worker_group ); MPI_Group_free ( &world_group ); if (i_am_the_server) { do { MPI_Recv(&request, 1, MPI_INT, MPI_ANY_SOURCE, REQUEST, world, &status); if (request) { for (i = 0; i < CHUNKSIZE; i++) rands[i] = random(); MPI_Send(rands, CHUNKSIZE, MPI_INT, status.MPI_SOURCE, REPLY, world); } } while ( request > 0 ); } else { request = 1; done = in = out = 0; max = INT_MAX; MPI_Send ( &request, 1, MPI_INT, server, REQUEST, world ); MPI_Comm_rank ( workers, &my_worker_rank ); iter = 0; while (! done) { iter++; request = 1; MPI_Recv( rands, CHUNKSIZE, MPI_INT, server, REPLY, world, &status ); for (i = 0; i < CHUNKSIZE;) { x = (((double) rands[i++])/max) * 2 - 1; y = (((double) rands[i++])/max) * 2 - 1; if (x * x + y * y < 1.0) in++; else out++; } MPI_Allreduce(&in, &totalin, 1, MPI_INT, MPI_SUM, workers); MPI_Allreduce(&out, &totalout, 1, MPI_INT, MPI_SUM, workers); Pi = (4.0*totalin)/(totalin + totalout); error = fabs( Pi - 3.141592653589793238462643); done = ((error < epsilon) || ((totalin + totalout) > 1000000)); request = (done) ? 0 : 1; if (i_am_the_master) { printf("\rpi = %23.20lf", Pi); fflush(stdout); MPI_Send( &request, 1, MPI_INT, server, REQUEST, world ); } else { if (request) MPI_Send( &request, 1, MPI_INT, server, REQUEST, world ); } } if (i_am_the_master) { printf("\npoints: %d\nin: %d, out: %d\n", totalin+totalout, totalin, totalout); } MPI_Comm_free(&workers); } } MPI_Finalize (); }