<< Chapter < Page | Chapter >> Page > |
To determine which strip of the global array we store and compute in this process, we call a utility routine called
MPE_DECOMP1D
that simply does several calculations to evenly split our 200 columns among our processes in contiguous strips. In the PVM version, we need to perform this computation by hand.
The
MPE_DECOMP1D
routine is an example of an extended MPI library call (hence the MPE prefix). These extensions include graphics support and logging tools in addition to some general utilities. The MPE library consists of routines that were useful enough to standardize but not required to be supported by all MPI implementations. You will find the MPE routines supported on most MPI implementations.
Now that we have our communicator group set up, and we know which strip each process will handle, we begin the computation:
* Start ColdDO C=0,COLS+1
DO R=0,ROWS+1BLACK(R,C) = 0.0
ENDDOENDDO
As in the PVM example, we set the plate (including boundary values) to zero.
All processes begin the time step loop. Interestingly, like in PVM, there is no need for any synchronization. The messages implicitly synchronize our loops.
The first step is to store the permanent heat sources. We need to use a routine because we must make the store operations relative to our strip of the global array:
* Begin running the time steps
DO TICK=1,MAXTIME* Set the persistent heat sourcesCALL STORE(BLACK,ROWS,COLS,S,E,ROWS/3,TOTCOLS/3,10.0,INUM)
CALL STORE(BLACK,ROWS,COLS,S,E,2*ROWS/3,TOTCOLS/3,20.0,INUM)CALL STORE(BLACK,ROWS,COLS,S,E,ROWS/3,2*TOTCOLS/3,-20.0,INUM)
CALL STORE(BLACK,ROWS,COLS,S,E,2*ROWS/3,2*TOTCOLS/3,20.0,INUM)
All of the processes set these values independently depending on which process has which strip of the overall array.
Now we exchange the data with our neighbors as determined by the Cartesian communicator. Note that we don’t need an IF test to determine if we are the far-left or far-right process. If we are at the edge, our neighbor setting is
MPI_PROC_NULL
and the
MPI_SEND
and
MPI_RECV
calls do nothing when given this as a source or destination value, thus saving us an IF test.
Note that we specify the communicator
COMM1D
because the rank values we are using in these calls are relative to that communicator:
* Send left and receive right
CALL MPI_SEND(BLACK(1,1),ROWS,MPI_DOUBLE_PRECISION,+ LEFTPROC,1,COMM1D,IERR)
CALL MPI_RECV(BLACK(1,MYLEN+1),ROWS,MPI_DOUBLE_PRECISION,+ RIGHTPROC,1,COMM1D,STATUS,IERR)* Send Right and Receive left in a single statement
CALL MPI_SENDRECV(+ BLACK(1,MYLEN),ROWS,COMM1D,RIGHTPROC,2,
+ BLACK(1,0),ROWS,COMM1D,LEFTPROC, 2,+ MPI_COMM_WORLD, STATUS, IERR)
Just to show off, we use both the separate send and receive, and the combined send and receive. When given a choice, it’s probably a good idea to use the combined operations to give the runtime environment more flexibility in terms of buffering. One downside to this that occurs on a network of workstations (or any other high-latency interconnect) is that you can’t do both send operations first and then do both receive operations to overlap some of the communication delay.
Notification Switch
Would you like to follow the 'High performance computing' conversation and receive update notifications?