// StructMPI.cpp // NKU CSC 333/601 - Fall 2002 - Kirby // ------------------------------------------------------------ // How to send and receive structures in MPI. // Optional! Not necessary for P4. // ------------------------------------------------------------ /************************************************************** Make sure your .rhosts file includes the lines: head.bobb.hpc.nku.edu yourusername b1.bobb.hpc.nku.edu yourusername b2.bobb.hpc.nku.edu yourusername b3.bobb.hpc.nku.edu yourusername b4.bobb.hpc.nku.edu yourusername b5.bobb.hpc.nku.edu yourusername b6.bobb.hpc.nku.edu yourusername b7.bobb.hpc.nku.edu yourusername b8.bobb.hpc.nku.edu yourusername b9.bobb.hpc.nku.edu yourusername b10.bobb.hpc.nku.edu yourusername b11.bobb.hpc.nku.edu yourusername NOTE: Contrary to earlier reports, there are only nodes 0-11, no node 12! Before running, turn on MPI (the -v option confirms which nodes are up) lamboot -v lamhosts To compile: mpiCC BasicMPI.cpp To run on 12 nodes: mpirun -np 12 a.out /***************************************************************/ #include #include #include #include using namespace std ; #include "mpi.h" // see class web page for dummy mpi.h const int N= 10 ; struct Bundle // A little homegrown type, for purposes of illustration. { double x ; int ar[N] ; } ; MPI_Datatype makeDatatypeForBundle() // Registers our "custom type" with MPI. { // Define the types of each slot in the struct MPI_Datatype types[2] ; types[0]= MPI_DOUBLE ; types[1]= MPI_INT ; // Define the lengths of each slot in the struct (# items of given type) int lengths[2] ; lengths[0]= 1 ; lengths[1]= N ; // Define the address of each slot relative to the start of the struct. assert( sizeof( MPI_Aint ) == sizeof( unsigned int ) ) ; unsigned int reladdrs[2] ; reladdrs[0]= 0 ; // x field starts 0 bytes into struct reladdrs[1]= sizeof( double ) ; // ar field starts 8 bytes into struct // Register your types with MPI. MPI_Datatype BUNDLETYPE ; MPI_Type_struct( 2, lengths, (MPI_Aint*) reladdrs, types, &BUNDLETYPE ) ; MPI_Type_commit( &BUNDLETYPE ) ; // Return type identifier to caller return BUNDLETYPE ; } int main( int argc, char** argv ) { // In this example, all messages bear the same tag. const int TAG= 99 ; // Turn on MPI. MPI_Init( &argc, &argv ) ; // How many processors are out there? int size ; MPI_Comm_size( MPI_COMM_WORLD, &size ) ; // Which processor am I? (0...size-1) int rank ; MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; // Get an MPI type identifier for our custom struct Bundle. MPI_Datatype BUNDLETYPE= makeDatatypeForBundle() ; // Create a vector of Bundles. vector v(5) ; // Put a bit of data in, to test transmission. v[3].x= 3.14 + rank ; v[3].ar[2]= rank ; // Print out what we've set if ( rank == 0 ) cout << v[3].x << " " << v[3].ar[2] << endl ; // Send to my "right" neighbor. int iDest= (rank+1) % size ; MPI_Send( &(v[0]), v.size(), BUNDLETYPE, iDest, TAG, MPI_COMM_WORLD ) ; // Receive my "left" neighbor's message data into my v. int iSource= (rank-1+size) % size ; // = (rank-1) mod size MPI_Status status ; MPI_Recv( &(v[0]), v.size(), BUNDLETYPE, iSource, TAG, MPI_COMM_WORLD, &status ) ; // Print out what we've received if ( rank == 0 ) cout << v[3].x << " " << v[3].ar[2] << endl ; // All done. MPI_Finalize() ; return 0 ; }