4.7 The SPMD model
-
There is only a single program
- There is no master program directing the computation
- Sometimes called hostless program
- There is still the issue of getting all the processes
initially started
- In the following example, the user starts the first copy
of the program
- By checking
pvm_parent()
, this copy can determine that
it was not spawn by a PVM task
- It then spawns multiple copies of itself and pass them the
array of tids
- At this point each copy is equal and can work on its
partition of the data, in collaboration with the other
processes
-
Example, the SPMD code:
spmd.c
#include "pvm3.h"
#define NPROC 4
main () {
int mytid ; /* my task id */
int tids[NPROC] ; /* array of task id */
int me ; /* my process number */
int i ;
/* enroll in pvm */
mytid = pvm_mytid () ;
/* find out if I am parent or child */
tids[0] = pvm_parent () ;
if (tids[0] < 0) { /* then I am the parent */
tids[0] = mytid ; me = 0 ;
/* start up copies of myself */
pvm_spawn ("spmd", (char**)0, 0, "", NPROC-1, &tids[1]) ;
/* multicast tids array to children */
pvm_initsend (PvmDataDefault) ;
pvm_pkint (tids, NPROC, 1) ;
pvm_mcast (&tids[1], NPROC-1, 0) ;
} else { /* I am a child */
/* receive tids array */
pvm_recv (tids[0], 0) ;
pvm_upkint (tids, NPROC, 1) ;
for (i=1; i<NPROC ; i++)
if (mytid == tids[i]) { me = i ; break ; }
}
/* all NPROC tasks are equal now */
/*-----------------------------------------------------------
* all NPROC tasks are equal now
* and can address each other by tids[0] thru tids[NPROC-1]
* for each process me => process number [0-(NPROC-1)]
*-----------------------------------------------------------
*/
printf ("me = %d mytid = %d\n", me, mytid) ;
dowork (me, tids, NPROC) ;
/* program finished exit pvm */
pvm_exit () ;
exit (1) ;
}
/* Simple example passes a token around a ring */
dowork (int me; int *tids; int nproc)
{
int token ;
int dest ;
int count = 1 ;
int stride = 1 ;
int msgtag = 4 ;
if (me == 0) {
token = tids[0] ;
pvm_initsend (PvmDataDefault) ;
pvm_pkint (&token, count, stride) ;
pvm_send (tids[me+1], msgtag) ;
pvm_recv (tids[nproc-1], msgtag) ;
printf ("token ring done\n") ;
} else {
pvm_recv (tids[me-1], msgtag) ;
pvm_upkint (&token, count, stride) ;
pvm_initsend (PvmDataDefault) ;
pvm_pkint (&token, count, stride) ;
dest = (me == nproc-1)? tids[0] : tids[me+1] ;
pvm_send (dest, msgtag) ;
}
}