4.6 The master/slave model
-
PVM is not restricted to this model
- Useful programming paradigm and simple to illustrate
- The master calls
pvm_mytid()
to
-
Allow it to use the PVM system, and
- Enable interprocessor communications
- It then call
pvm_spawn()
to execute a given number of
slave programs on other machines
- Each slave program must also call
pvm_mytid()
to enable
processor communications
- Subsequently,
pvm_send()
and pvm_recv()
are used to
pass messages between processes
- When finished, all the PVM programs should call
pvm_exit()
to
-
Allow PVM to disconnect any sockets to the processes, and
- Allow PVM to keep track of which processes are running
-
Example: the master code
master.c
#include "pvm3.h"
#define SLAVENAME "slave"
main()
{
int mytid ; /* my task id */
int tids[32] ; /* slave task ids */
int n, nproc, i, who, msgtype ;
float data[100], result[32] ;
/* enroll in pvm */
mytid = pvm_mytid () ;
/* start up slave tasks */
puts ("How many slave programs (1-32)?") ;
scanf ("%d", &nproc) ;
pvm_spawn (SLAVENAME, (char**)0, 0, "", nproc, tids) ;
/* Begin User Program */
n = 100 ;
/* initialize_data (data, n) ; */
for (i=0; i<n; i++){
data[i] = 1 ;
}
/* Broadcast initial data to slave tasks */
pvm_initsend (PvmDataDefault) ;
pvm_pkint (&nproc, 1, 1) ;
pvm_pkint (tids, nproc, 1) ;
pvm_pkint (&n, 1, 1) ;
pvm_pkfloat (data, n, 1) ;
pvm_mcast (tids, nproc, 0) ;
/* Wait for results from slaves */
msgtype = 5 ;
for (i=0; i<nproc; i++){
pvm_recv (-1, msgtype) ;
pvm_upkint (&who, 1, 1) ;
pvm_upkfloat (&result[who], 1, 1) ;
printf ("I got %f from %d\n", result[who], who) ;
}
/* Program Finished exit PVM before stopping */
pvm_exit () ;
}
-
Example: the slave code
slave.c
main () {
int mytid ; /* my task id */
int tids[32] ; /* task ids */
int n, me, i, nproc, master, msgtype ;
float data[100], result, work() ;
/* enroll in pvm */
mytid = pvm_mytid () ;
/* Receive data from master */
msgtype = 0 ;
pvm_recv (-1, msgtype) ;
pvm_upkint (&nproc, 1, 1) ; pvm_upkint (tids, nproc, 1) ;
pvm_upkint (&n, 1, 1) ; pvm_upkfloat (data, n, 1) ;
/* Determine which slave I am (0 -- nproc-1) */
for (i=0; i<nproc ; i++)
if (mytid == tids[i]) { me = i ; break ; }
/* Do calculations with data */
result = work (me, n, data, tids, nproc) ;
/* Send result to master */
pvm_initsend (PvmDataDefault) ;
pvm_pkint (&me, 1, 1) ; pvm_pkfloat (&result, 1, 1) ;
msgtype = 5 ; master = pvm_parent () ;
pvm_send (master, msgtype) ;
/* Program finished. Exit PVM before stopping */
pvm_exit () ;
}
float work (int me; int n; float *data; int *tids; int nproc)
{
int i, dest ;
float psum = 0.0 ;
float sum = 0.0 ;
for (i=0 ; i<n ; i++)
sum += me * data[i] ;
/* illustrate node-to-node communication */
pvm_initsend (PvmDataDefault) ;
pvm_pkfloat (&sum, 1, 1) ;
dest = me+1 ;
if (dest == nproc) dest = 0 ;
pvm_send (tids[dest], 22) ;
pvm_recv (-1, 22) ;
pvm_upkfloat (&psum, 1, 1) ;
return (sum+psum) ;
}