CSC352 MPI pi2.c program

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 15:39, 22 October 2013 (EDT)


// pi2.c
// D. Thiebaut
// Computes Pi using 2 processes under MPI
// 
// To compile and run:
// mpicc -o pi2 pi2.cpp
// time mpirun -np 2 ./pi2 100000000
//
// Output
// Process 1 of 2 started on beowulf2.  N= 50000000
// Process 0 of 2 started on beowulf2.  N= 50000000
//  50000000 iterations: Pi = 3.14159
//
//  real0m1.251s
//  user0m1.240s
//  sys0m0.000s
//

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

#define MANAGER 0
#define WORKER  1
#define NN      100000

//--------------------------------------------------------------------
//                         P R O T O T Y P E S
//--------------------------------------------------------------------
void doManager( int );
void doWorker( );

//--------------------------------------------------------------------
//                           M  A  I  N
//--------------------------------------------------------------------
int main(int argc, char *argv[]) {
  int myId, noProcs, nameLen;
  char procName[MPI_MAX_PROCESSOR_NAME];
  int N;

  if ( argc<2 ) {
    printf( "Syntax: mpirun -np 2 pi2 N\n" );
    return 1;
  }

  // get the number of samples to generate
  N = atoi( argv[1] );
  
  //--- start MPI ---
  MPI_Init( &argc, &argv);
  MPI_Comm_rank( MPI_COMM_WORLD, &myId );
  MPI_Comm_size( MPI_COMM_WORLD, &noProcs );
  MPI_Get_processor_name( procName, &nameLen );
  
  //--- display which process we are, and how many there are ---
  printf( "Process %d of %d started on %s. N = %d\n", 
	  myId,  noProcs, procName, N );

  //--- farm out the work: 1 manager, several workers ---
  if ( myId == MANAGER ) 
    doManager( N );
  else
    doWorker( );
  
  //--- close up MPI ---
  MPI_Finalize();
  
  return 0;
}

//--------------------------------------------------------------------
// The function to be evaluated
//--------------------------------------------------------------------
double f( double x ) {
  return 4.0 / ( 1.0 + x*x );
}

//--------------------------------------------------------------------
// The manager's main work function
//--------------------------------------------------------------------
void doManager( int n ) {
  double sum0 = 0, sum1;
  double deltaX = 1.0/n;
  int i;
  MPI_Status status;

  //--- first send n to worker ---
  MPI_Send( &n, 1, MPI_INT, WORKER, 0, MPI_COMM_WORLD );

  //--- perform 1st half of the work ---
  for ( i=0; i< n/2; i++ )
    sum0 += f( i * deltaX );

  //--- wait for other half from worker ---
  MPI_Recv( &sum1, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status );

  //--- output result ---
  printf( "%d iterations: Pi = %f\n", n, ( sum0 + sum1 )*deltaX );
}

//--------------------------------------------------------------------
// The worker's main work function
//--------------------------------------------------------------------
void doWorker( ) {
  int n, i;

  //--- get n from manager ---
  MPI_Status status;
  MPI_Recv( &n, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status );

  //--- do (second) half of the work ---
  double sum = 0;
  double deltaX = 1.0/n;

  for ( i=n/2; i< n; i++ )
    sum += f( i * deltaX );

  //-- send result to manager ---
  MPI_Send( &sum, 1, MPI_DOUBLE, MANAGER, 0, MPI_COMM_WORLD );
}