PI


/*      pi.c
 *
 *      Computation of pi by a "montecarlo" method:
 *      Every process computes a number of points in the unit square
 *      and returns the number of hits in the quarter circle
 *      pi is  #hits/#total * 4
 *      
 *      usage:
 *              pi [total]
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mpi.h>

#define TAG_WORK         1
#define TAG_RESULT       2
#define DEFAULT_ANZAHL   10000L       /* Defaultwert für Anzahl */

void main(int argc, char *argv[])
{
  int    myid;
  void   master(int argc, char *argv[]);
  void   slave(void);
   
  /* start MPI */
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &myid);
  
  if  (myid == 0) {
    master(argc, argv);
  } else {
    slave();
  }

  /* leave MPI */
  MPI_Finalize();
}

void master(int argc, char *argv[])
{
  long        total;                    /* total number of points */
  long        mytotal;                  /* number of points per process */
  long        myhits;                   /* number of hits per process */
  long        totalhits;                /* total number of hits */
  double      pi;                       /* result */
  int         nproc;                    /* number of processes */
  MPI_Status  status;
  int         i;
  long        calc(long total);         /* calculation */
  
  /* compute number of points per process */
  if (argc != 2) {
    total = DEFAULT_ANZAHL;
  } else {
    total = 1000 * atol(argv[1]);
  }
  MPI_Comm_size(MPI_COMM_WORLD, &nproc);
  mytotal = (long) ceil(total/nproc);
  total = nproc * mytotal;              /* correct total */
  
  /* send work to all processes */
  for (i=1; i<nproc; i++) {
    MPI_Send(&mytotal, 1, MPI_LONG, i, TAG_WORK, MPI_COMM_WORLD);
  }
  
  /*  compute partial results */
  myhits = calc(mytotal);
  
  /* combine partial results */
  totalhits = myhits;
  for (i = 1; i < nproc; i++) {
    MPI_Recv(&myhits, 1, MPI_LONG, MPI_ANY_SOURCE, TAG_RESULT,
	     MPI_COMM_WORLD, &status);
    totalhits += myhits;
  }  
  
  /* compute final result */
  pi = totalhits/(double)total*4;
  printf("\nPI = %lf\n", pi);
}

void slave(void)
{
  long   mytotal;                       /* number of points per process */
  long   myhits;                        /* number of hits per process */
  MPI_Status      status;
  long   calc(long total);              /* calculation */
  
  
  /* get work from master */
  MPI_Recv(&mytotal, 1, MPI_LONG, 0, TAG_WORK, MPI_COMM_WORLD, &status);
  
  /*  compute partial results */
  myhits = calc(mytotal);
  
  /* send result to master */
  MPI_Send(&myhits, 1, MPI_LONG, 0, TAG_RESULT, MPI_COMM_WORLD);
}

#include <sys/types.h>

long calc(long total)
{
  /* 
   * compute total random points in the unit square
   * and return the number of hits in the sector (x*x + y*y < 1)
   */
  
  double  x, y;                     /* random coordinates */
  long    hits = 0;                 /* number of hits */
  long     i;
  
  /* initialize random generator (otherwise all return the same result!) */
  srand(getpid());
  
  for(i=0; i<total; i++) {
    x = ((double) rand())/RAND_MAX;
    y = ((double) rand())/RAND_MAX;
      
    if ( x*x + y*y <= 1.0 ) {
      hits++;
    }
  }
  
  return(hits); 
}

previous    contents     next

Peter Junglas 11.5.2000