Search code examples
cparallel-processingmpipisrand

Why is the result when executing this C MPI application for Pi approximation always the same?


This C MPI application for Pi approximation always prints out the same result per problem size, which is the number of random generated dots (npts).

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

int main(int argc, char *argv[]) {

  int myid,nprocs;

  double PI25DT = 3.141592653589793238462643;

  long long npts = 1e10;

  long i,mynpts;

  long double f,sum,mysum;
  long double xmin,xmax,x;

  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
  MPI_Comm_rank(MPI_COMM_WORLD,&myid);

  if (myid == 0) {
    mynpts = npts - (nprocs-1)*(npts/nprocs);
  } else {
    mynpts = npts/nprocs;
  }

  mysum = 0.0;
  xmin = 0.0;
  xmax = 1.0;

  srand(myid);  

  for (i=0; i<mynpts; i++) {
    x = (long double) rand()/RAND_MAX*(xmax-xmin) + xmin;
    mysum += 4.0/(1.0 + x*x);
  }

  MPI_Reduce(&mysum,&sum,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);

  if (myid == 0) {
    f = sum/npts;
    printf("PI calculated with %lld points = %.16f \n",npts,f);
    printf("Error is: %.16f \n",fabs(f-PI25DT));
  }

  MPI_Finalize();
}  

This is the output. I think the result should differ a bit for each run of the application. I execute it on a cluster with 128 nodes.

$ mpicc pi.c -o /mnt/cluster_128/pi
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi  /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi  /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi  /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi  /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 

Solution

  • You're seeding the PRNG here:

    srand(myid);
    

    myid is a value set by your call to MPI_Comm_rank() and you're only interested in results for myid == 0, so this is always the same value. Seeding the same value yields the same sequence of "random" numbers.

    Use the common idiom of seeding instead:

    #include <time.h>
    #include <stdlib.h>
    
    [...]
    
    srand(time(0));