"Whisper Game" Example: Node 0: declare memory for string string = "Hello world!" mytype = 5 dst = 1 send(mytype, string, dst) receive(5, buffer) Node 1: declare memory for buffer receive(5, buffer) send(5, buffer, 2) Node 2: declare memory for buffer receive(5, buffer) send(5, buffer, 3) ... Node 14: declare memory for buffer receive(5, buffer) send(5, buffer, 15) Node 15: declare memory for buffer receive(5, buffer) send(5, buffer, 0) BUT Contents must be specified with start and length Each node could run more than one process (usually not) Usually want to write one program and customize on each node -- SPMD -- single program multiple data ^L Example in MPI -- same program on all nodes #include "mpi.h" #include #define BUFLEN 512 int main(argc,argv) int argc; char *argv[]; { int i, myid, numprocs, next, rc, namelen; char buffer[BUFLEN], processor_name[MPI_MAX_PROCESSOR_NAME]; double startwtime, endwtime; MPI_Status status; /* Initialize the MPI execution environment */ MPI_Init(&argc,&argv); /* * Determines the size of the group associated * with a communicator * * int MPI_Comm_size ( comm, size ) * MPI_Comm comm; // communicator (handle) * int *size; // number of processes in the group of comm (integer) */ MPI_Comm_size(MPI_COMM_WORLD,&numprocs); /* * Determines the rank of the calling process in the * communicator * * int MPI_Comm_rank ( comm, rank ) * MPI_Comm comm; // communicator (handle) * int *rank; // rank of the calling process in group of * // comm (integer) */ MPI_Comm_rank(MPI_COMM_WORLD,&myid); /* * Gets the name of the processor * * int MPI_Get_processor_name( name, resultlen ) * char *name; // A unique specifier for the actual * // (as opposed to virtual) node. * int *resultlen; // Length (in characters) of the name */ MPI_Get_processor_name(processor_name,&namelen); fprintf(stderr,"Process %d on %s\n", myid, processor_name); strcpy(buffer,"hello there"); if (myid == numprocs-1) next = 0; else next = myid+1; if (myid == 0) { printf("%d sending '%s' \n",myid,buffer); /* * Returns an elapsed time on the calling processor */ startwtime = MPI_Wtime(); /* * Performs a basic send * * int MPI_Send( buf, count, datatype, dest, tag, comm ) * void *buf; // initial address of send buffer (choice) * int count; // number of elements in send buffer * // (nonnegative integer) * int dest; // rank of destination (integer) * MPI_Datatype datatype; // datatype of each send buffer * // element (handle) * int tag; // message tag (integer) * MPI_Comm comm; //communicator (handle) */ MPI_Send(buffer, strlen(buffer)+1, MPI_CHAR, next, 99, MPI_COMM_WORLD); printf("%d receiving \n",myid); /* * Basic receive * * int MPI_Recv( buf, count, datatype, source, tag, comm, status ) * void *buf; //initial address of receive buffer (choice) * int count; // maximum number of elements in receive buffer * // (integer) * MPI_Datatype datatype; // datatype of each receive buffer * // element (handle) * int source; // rank of source (integer) * int tag; // message tag (integer) * MPI_Comm comm; // communicator (handle) * MPI_Status *status; // status object (Status) */ MPI_Recv(buffer, BUFLEN, MPI_CHAR, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD, &status); printf("%d received '%s' \n",myid,buffer); } else { printf("%d receiving \n",myid); MPI_Recv(buffer, BUFLEN, MPI_CHAR, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD, &status); printf("%d received '%s' \n",myid,buffer); MPI_Send(buffer, strlen(buffer)+1, MPI_CHAR, next, 99, MPI_COMM_WORLD); printf("%d sent '%s' \n",myid,buffer); } /* * Blocks until all process have reached this routine. * * int MPI_Barrier ( comm ) * MPI_Comm comm; // communicator (handle) */ MPI_Barrier(MPI_COMM_WORLD); if (myid == 0) { endwtime = MPI_Wtime(); printf("wall clock time = %f\n", endwtime-startwtime); } /* * Terminates MPI execution environment * * int MPI_Finalize() */ MPI_Finalize(); }