next up previous
Next: The synopsis of Up: Lesson 4 -- Previous: Lesson 4 --

The listing of fifth.c

 

#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 ();
}



Zdzislaw Meglicki
Tue Feb 28 15:07:51 EST 1995