Difference between revisions of "CSC352 Homework 4 Solutions"
Line 484: | Line 484: | ||
=Problem 3= | =Problem 3= | ||
+ | <br /> | ||
+ | A good program by Danae for the MPI question. Note the use of '''perworker''' and '''permanager''' to make sure the total number of samples adds up ''exactly'' to '''numsamples'''. Nice touch. | ||
<br /> | <br /> | ||
<source lang="C"> | <source lang="C"> | ||
+ | [352a@beowulf 352a-aa]$ cat mpiMonteCarlo4.c | ||
+ | /* mpiMonteCarlo4.c | ||
+ | // danae | ||
+ | // | ||
+ | // Computes Pi using the Monte Carlo method with MPI, | ||
+ | // NP (user-specified) processes, and N random samples. | ||
+ | // Note that N should be evenly divisible by NP in order | ||
+ | // to truly calculate N samples. | ||
+ | // | ||
+ | // To compile and run: | ||
+ | // mpicc -o mpiMonteCarlo4 mpiMonteCarlo4.c | ||
+ | // mpirun -np [NP] ./mpiMonteCarlo [N] | ||
+ | // | ||
+ | */ | ||
+ | |||
+ | #include "mpi.h" | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | #define MANAGER 0 | ||
+ | |||
+ | //-------------------------------------------------------------------- | ||
+ | // P R O T O T Y P E S | ||
+ | //-------------------------------------------------------------------- | ||
+ | void doManager(int,int); | ||
+ | void doWorker(); | ||
+ | |||
+ | //-------------------------------------------------------------------- | ||
+ | // M A I N | ||
+ | //-------------------------------------------------------------------- | ||
+ | int main(int argc, char *argv[]) { | ||
+ | int myId, noProcs, nameLen; | ||
+ | char procName[MPI_MAX_PROCESSOR_NAME]; | ||
+ | int numsamples; | ||
+ | |||
+ | if ( argc<2 ) { | ||
+ | printf( "Please Use Correct Syntax: mpirun -np [NP] ./pi2 [N]\n" ); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | // get the number of samples to generate | ||
+ | numsamples = 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 on --- | ||
+ | printf( "Process %d of %d started.\n", myId, noProcs); | ||
+ | |||
+ | //--- farm out the work: 1 manager, several workers --- | ||
+ | if ( myId == MANAGER ) | ||
+ | doManager(noProcs, numsamples); | ||
+ | else | ||
+ | doWorker(); | ||
+ | |||
+ | //--- close up MPI --- | ||
+ | MPI_Finalize(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------------- | ||
+ | // The manager's main work function | ||
+ | //-------------------------------------------------------------------- | ||
+ | void doManager(int noProcs, int numsamples ) { | ||
+ | double incircle = 0; | ||
+ | double workersum; | ||
+ | int i; | ||
+ | MPI_Status status; | ||
+ | |||
+ | int perworker = (1.0)*numsamples/noProcs; | ||
+ | int permanager = numsamples - perworker*noProcs; //manager picks up slack | ||
+ | |||
+ | // printf("perworker: %d\n", perworker); | ||
+ | //--- first to all workers --- | ||
+ | for(i=1; i<noProcs; i++) { | ||
+ | MPI_Send( &perworker, 1, MPI_INT, i, 0, MPI_COMM_WORLD ); | ||
+ | } | ||
+ | |||
+ | //calculate manager portion | ||
+ | srand(time(NULL)); //seed the random number generator with time | ||
+ | float x, y; | ||
+ | for(i=0; i<permanager+perworker; i++) { | ||
+ | x = 1 - (((float)rand()/(float)(RAND_MAX)) * 2.0); //random float [-1,1] | ||
+ | y = 1 - (((float)rand()/(float)(RAND_MAX)) * 2.0); //random float [-1,1] | ||
+ | if ((float)x*x + (float)y*y <= (float)(1.0)) { | ||
+ | incircle += 1; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //--- wait for worker sums --- | ||
+ | for(i=1; i<noProcs; i++) { | ||
+ | MPI_Recv( &workersum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status ); | ||
+ | incircle += workersum; | ||
+ | } | ||
+ | |||
+ | //--- output result --- | ||
+ | printf( "%d iterations: Pi = %f\n", permanager + noProcs*perworker, 4.0*(incircle)/(noProcs*perworker)); | ||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------------- | ||
+ | // The worker's main work function | ||
+ | //-------------------------------------------------------------------- | ||
+ | void doWorker( ) { | ||
+ | int numthrows, i; | ||
+ | |||
+ | //--- get n from manager --- | ||
+ | MPI_Status status; | ||
+ | MPI_Recv( &numthrows, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status ); | ||
+ | |||
+ | //--- do portion of the work --- | ||
+ | double incircle = 0; | ||
+ | float x, y; | ||
+ | for (i=0; i<numthrows; i++) { | ||
+ | // generate random x, y as float [0,2], subtracts 1 to be in range [-1,1] | ||
+ | x = 1 - (((float)rand()/(float)(RAND_MAX)) * 2.0); //random float [-1,1] | ||
+ | y = 1 - (((float)rand()/(float)(RAND_MAX)) * 2.0); //random float [-1,1] | ||
+ | if ((float)x*x + (float)y*y <= (float)(1.0)) | ||
+ | incircle += 1; | ||
+ | } | ||
+ | |||
+ | //-- send result to manager --- | ||
+ | MPI_Send( &incircle, 1, MPI_DOUBLE, MANAGER, 0, MPI_COMM_WORLD ); | ||
+ | } | ||
+ | |||
</source> | </source> |
Latest revision as of 14:46, 8 November 2013
--D. Thiebaut (talk) 14:41, 8 November 2013 (EST)