C ------------------------------------------------------------------------ C pi_send.f C FILES: pi_send.f, dboard.f, make.pi.f C DESCRIPTION: MPI pi calculation example program. Fortran version. C This program calculates pi using a "dartboard" algorithm. See C Fox et al.(1988) Solving Problems on Concurrent Processors, vol.1 C page 207. All processes contribute to the calculation, with the C master averaging the values for pi. C C SPMD Version: Conditional statements check if the process is the C master or a worker. C C This version uses low level sends and receives to collect results C C AUTHOR: Roslyn Leibensperger (C program for PVM). C REVISED: 05/11/93 Blaise Barney Ported to Fortran. C 05/24/93 R. Leibensperger Ported to API. C 01/10/94 S. Pendell Changed API to MPL. C 05/18/94 R. Leibensperger Non-blocking send. C CONVERTED TO MPI: 11/12/94 by Xianneng Shen. C ------------------------------------------------------------------------ C Explanation of constants and variables used in this program: C DARTS = number of throws at dartboard C ROUNDS = number of times "DARTS" is iterated C MASTER = task ID of master task C mytid = task ID of current task C nproc = number of tasks C homepi = value of pi calculated by current task C pi = average of pi for this iteration C avepi = average pi value for all iterations C pirecv = pi received from worker C pisum = sum of workers' pi values C seednum = seed number - based on mytid C source = source of incoming message C mtype = message type C sbytes = size of message being sent C nbytes = size of message successfully sent C rbytes = size of message received C ------------------------------------------------------------------------ program pi_send include 'mpif.h' integer DARTS, ROUNDS, MASTER parameter(DARTS = 5000) parameter(ROUNDS = 10) parameter(MASTER = 0) integer ierr, status(MPI_STATUS_SIZE), request integer mytid, nproc, source, mtype, msgid, sbytes, rbytes, & i, n real*4 seednum real*8 homepi, pi, avepi, pirecv, pisum, dboard C Obtain number of tasks and task ID call mpi_init(ierr) call mpi_comm_rank(MPI_COMM_WORLD, mytid, ierr) call mpi_comm_size(MPI_COMM_WORLD, nproc, ierr) write(*,*)'MPI task id = ', mytid C Use the task id to set the seed number for the random number generator. seednum = real(mytid) call srand(seednum) avepi = 0 do 40 i = 1, ROUNDS C Calculate pi using dartboard algorithm homepi = dboard(DARTS) C ******************** start of worker section *************************** C All workers send result to master. Steps include: C -set message type equal to this round number C -set message size to 8 bytes (size of real8) C -send local value of pi (homepi) to master task C -a non-blocking send followed by mpi_wait is used C this is safe programming practice if (mytid .ne. MASTER) then mtype = i sbytes = 8 call mpi_isend(homepi, 1, MPI_DOUBLE_PRECISION, . MASTER, i, MPI_COMM_WORLD, request, ierr) call mpi_wait(request, status, ierr) C ******************** end of worker section ***************************** else C ******************** start of master section ************************** C Master receives messages from all workers. Steps include: C -set message type equal to this round C -set message size to 8 bytes (size of real8) C -receive any message of type mytpe C -keep running total of pi in pisum C Master then calculates the average value of pi for this iteration C Master also calculates and prints the average value of pi over all C iterations mtype = i sbytes = 8 pisum = 0 do 30 n = 1, nproc-1 call mpi_recv(pirecv, 1, MPI_DOUBLE_PRECISION, . MPI_ANY_SOURCE, mtype, MPI_COMM_WORLD, status, ierr) pisum = pisum + pirecv 30 continue pi = (pisum + homepi)/nproc avepi = ((avepi*(i-1)) + pi) / i write(*,32) DARTS*i, avepi 32 format(' After',i6,' throws, average value of pi = ',f10.8) C ********************* end of master section **************************** endif 40 continue call mpi_finalize(ierr) end