/* void process( const Eref& e, ProcPtr p ) { for ( unsigned int i = 0; i < numNodes; ++i ){ if ( i != myNode ) { isend( outbuf_[i] ); inbufNum = recv(from anywhere) readBuf( inbuf_[inbufNum] ); } } } vector< vector< double > > outBuf_; // outbuf[tgtnode][data] vector< vector< double > > inBuf_;// inbuf[srcnode][data] // Things to monitor: // - The send happens with a standard buf size, and if the contents // exceed it there is a signal to this effect and the rest of it is sent // right away as a big block. // - The Recv likewise // // mpi_testsome checks which msgs have been received. // // // Assumes we already have an irecv out for all the nodes. // void checkIncoming() { MPI_request* array_of_requests; MPI_status* array_of_statuses; MPI_testsome() int MPI_Testsome(int incount, MPI_Request array_of_requests[], int *outcount, int array_of_indices[], MPI_Status array_of_statuses[]) for ( unsigned int MPI_Irecv (&buf,count,datatype,source,tag,comm,&request) } main() { } */ #include <mpi.h> #include <vector> using namespace std; #define WORKTAG 1 #define DIETAG 2 /* Local functions */ const int numEntries = 10; static void master(void); static void slave(void); static double* get_next_work_item() { static vector< double > ret( numEntries ); static unsigned int numCalls = 0; for ( unsigned int i = 0; i < numEntries; ++i ) ret[i] = i + numCalls; numCalls++; if ( numCalls > 1000 ) return 0; return &ret[0]; } static double do_work(double* work); int main(int argc, char **argv) { int myrank; /* Initialize MPI */ MPI_Init(&argc, &argv); /* Find out my identity in the default communicator */ MPI_Comm_rank(MPI_COMM_WORLD, &myrank); if (myrank == 0) { master(); } else { slave(); } /* Shut down MPI */ MPI_Finalize(); return 0; } static void master(void) { int ntasks, rank; double* work; double result; MPI_Status status; double tot = 0.0; /* Find out how many processes there are in the default communicator */ MPI_Comm_size(MPI_COMM_WORLD, &ntasks); /* Seed the slaves; send one unit of work to each slave. */ for (rank = 1; rank < ntasks; ++rank) { /* Find the next item of work to do */ work = get_next_work_item(); /* Send it to each rank */ MPI_Send(work, /* message buffer */ numEntries, /* one data item */ MPI_DOUBLE, /* data item is a double */ rank, /* destination process rank */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */ } /* Loop over getting new work requests until there is no more work to be done */ work = get_next_work_item(); while (work != NULL) { /* Receive results from a slave */ MPI_Recv(&result, /* message buffer */ 1, /* one data item */ MPI_DOUBLE, /* of type double real */ MPI_ANY_SOURCE, /* receive from any sender */ MPI_ANY_TAG, /* any type of message */ MPI_COMM_WORLD, /* default communicator */ &status); /* info about the received message */ /* Send the slave a new work unit */ MPI_Send(work, /* message buffer */ numEntries, /* one data item */ MPI_DOUBLE, /* data item is an integer */ status.MPI_SOURCE, /* to who we just received from */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */ /* Get the next unit of work to be done */ work = get_next_work_item(); tot += result; } /* There's no more work to be done, so receive all the outstanding results from the slaves. */ for (rank = 1; rank < ntasks; ++rank) { MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); tot += result; } /* Tell all the slaves to exit by sending an empty message with the DIETAG. */ for (rank = 1; rank < ntasks; ++rank) { MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD); } cout << "Tot = " << tot << endl; } static void slave(void) { double work[numEntries]; double result; MPI_Status status; while (1) { /* Receive a message from the master */ MPI_Recv( work, numEntries, MPI_DOUBLE, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); /* Check the tag of the received message. */ if (status.MPI_TAG == DIETAG) { return; } /* Do the work */ result = do_work(work); /* Send the result back */ MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } } static double do_work(double* work) { double tot = 0; for (int i =0; i < numEntries; ++i ) tot += work[i]; }