/** \file mpiExample2.cpp \brief MPI programming example #2. \author george j. grevera, ph.d. This program is a skeleton of a parallel MPI application using the one manager/many workers framework. The process with an MPI rank of 0 is considered to be the manager; processes with MPI ranks of 1..mpiSize-1 are workers. Messages are defined and are sent from the manager to the workers.
compile:  mpic++ -g  -o mpiExample2.exe mpiExample2.cpp  # debug version
          mpic++ -O3 -o mpiExample2.exe mpiExample2.cpp  # optimized version
run    :  lamboot -v    # to start lam mpi
          mpirun -np 4 ./mpiExample2.exe  # run in parallel w/ 4 processes
          lamhalt       # to stop lam mpi
*/ #include #include #include #include static char mpiName[ 1024 ]; ///< host computer name static int mpiRank; ///< number of this process (0..n-1) static int mpiSize; ///< total number of processes (n) static int myPID; ///< process id /** \brief format of messages sent between manager and worker processes for example 2. \todo define parameters for OP_WORK. \todo define parameters for OP_RESULT. */ struct Message { enum { OP_WORK, ///< manager to worker - here's your work assignment OP_EXIT, ///< manager to worker - time to exit OP_RESULT ///< worker to manager - here's the result }; int operation; ///< one of the above /** \todo define operation specific parameters here. */ }; //---------------------------------------------------------------------- /** \brief manager code for example 2. */ static void manager ( void ) { printf( "manager: my rank=%d, size=%d, pid=%d. \n", mpiRank, mpiSize, myPID ); /** \todo insert manager code here. */ //as an example, send an empty work message to each worker struct Message m; m.operation = m.OP_WORK; assert( mpiSize>3 ); MPI_Send( &m, sizeof( m ), MPI_UNSIGNED_CHAR, 1, m.operation, MPI_COMM_WORLD ); MPI_Send( &m, sizeof( m ), MPI_UNSIGNED_CHAR, 2, m.operation, MPI_COMM_WORLD ); MPI_Send( &m, sizeof( m ), MPI_UNSIGNED_CHAR, 3, m.operation, MPI_COMM_WORLD ); } //---------------------------------------------------------------------- /** \brief worker code for example 2. */ static void worker ( void ) { printf( "worker: my rank=%d, size=%d, pid=%d. \n", mpiRank, mpiSize, myPID ); /** \todo insert worker code here. */ //as an example, receive a message MPI_Status status; struct Message m; MPI_Recv( &m, sizeof( m ), MPI_UNSIGNED_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status ); printf( "worker %d (%d): received message. \n", mpiRank, myPID ); } //---------------------------------------------------------------------- /** \brief main program entry point for example 2. execution begins here. \param argc count of command line arguments. \param argv array of command line arguments. \returns 0 is always returned. */ int main ( int argc, char* argv[] ) { //not const because MPI_Init may change if (MPI_Init( &argc, &argv ) != MPI_SUCCESS) { //actually, we'll never get here but it is a good idea to check. // if MPI_Init fails, mpi will exit with an error message. puts( "mpi init failed." ); return 0; } //get the name of this computer gethostname( mpiName, sizeof( mpiName ) ); //determine rank MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank ); //determine the total number of processes MPI_Comm_size( MPI_COMM_WORLD, &mpiSize ); //get the process id myPID = getpid(); printf( "mpi initialized. my rank=%d, size=%d, pid=%d. \n", mpiRank, mpiSize, myPID ); if (mpiSize<2) { puts("this example requires at least 1 manager and 1 worker process."); MPI_Finalize(); return 0; } if (mpiRank==0) manager(); else worker(); MPI_Finalize(); return 0; } //----------------------------------------------------------------------