// // Open Systems Laboratory // http://www.lam-mpi.org/tutorials/ // Indiana University // // MPI Tutorial // Lab 2: The cannonical ring program // // Mail questions regarding tutorial material to lam at lam dash mpi dot org // #include #include using namespace std; int main(int argc, char *argv[]) { int num; int rank, size, tag, next, from; MPI::Status status; // Start up MPI MPI::Init(argc, argv); rank = MPI::COMM_WORLD.Get_rank(); size = MPI::COMM_WORLD.Get_size(); // Arbitrarily choose 201 to be our tag. Calculate the rank of the // next process in the ring. Use the modulus operator so that the // last process "wraps around" to rank zero. tag = 201; next = (rank + 1) % size; from = (rank + size - 1) % size; // If we are the "console" process, get a integer from the user to // specify how many times we want to go around the ring if (rank == 0) { cout << "Enter the number of times around the ring: "; cin >> num; cout << "Process " << rank << " sending " << num << " to " << next << endl; MPI::COMM_WORLD.Send(&num, 1, MPI::INT, next, tag); } // Pass the message around the ring. The exit mechanism works as // follows: the message (a positive integer) is passed around the // ring. Each time is passes rank 0, it is decremented. When each // processes receives the 0 message, it passes it on to the next // process and then quits. By passing the 0 first, every process // gets the 0 message and can quit normally. do { MPI::COMM_WORLD.Recv(&num, 1, MPI::INT, from, tag, status); cout << "Process " << rank << " received " << num << endl; if (rank == 0) { num--; cout << "Process 0 decremented num" << endl; } cout << "Process " << rank << " sending " << num << " to " << next << endl; MPI::COMM_WORLD.Send(&num, 1, MPI::INT, next, tag); } while (num > 0); cout << "Process " << rank << " exiting" << endl; // The last process does one extra send to process 0, which needs to // be received before the program can exit if (rank == 0) MPI::COMM_WORLD.Recv(&num, 1, MPI::INT, from, tag, status); // Quit MPI::Finalize(); return 0; }