// structMPI.c // Send a structure datatype //http://www.uic.edu/depts/accc/hardware/argo/mpi_routines.html //See the MPI_Address example /* This program is sending a "struct" of 5 elements: * 1-3: 3 floats * 4: 1 int * 5: array of 6 ints */ #include #include "mpi.h" #define elements 5 // There are 5 elements in the "struct" // (the fifth element is an array of 6 ints) /* Derived datatype example program. Sending different types of data to other processes */ int main( int argc, char *argv[]) { int numprocs, myrank,loop; /* variables to pass to other processes */ /* These elements represent our "struct" */ float x=10.0, y=20.0, z=30.0; int a=9; int b[6]={3,4,5,6,7,8}; // Each block of the "struct" has 1 element, except for the last with 6: int blocks[elements] = {1,1,1,1,6}; MPI_Aint disp[elements]; // "Address int" MPI_Aint addresses[elements]; /* Define the types of variables to transmit */ MPI_Datatype type_of_data[elements] = {MPI_FLOAT,MPI_FLOAT,MPI_FLOAT,MPI_INT,MPI_INT}; MPI_Aint next_address; MPI_Datatype pointer_to_new_mpi_type; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); if (myrank == 0) { printf("\nExample of sending multiple variables, of various types, "); printf("to other processes.\n\n"); } /* Element #5 in the list of items to pass is a pointer to a six element array. Indicate that there are six elements. */ blocks[4] = 6; /* Get the address of each element to pass */ /* x is at 0 blocks from the start of "addresses" * y is at 1 block, z is at 2 blocks, etc */ MPI_Address(&x,addresses+0); MPI_Address(&y,addresses+1); MPI_Address(&z,addresses+2); MPI_Address(&a,addresses+3); MPI_Address(&b,addresses+4); /* Calculate relative address of the variables from the first variable, x, in the list of items to pass. For example, address[1] - address[0] is the actual difference in the value of the addresses for y and x. */ for (loop = 0; loop < elements; loop++) { disp[loop] = addresses[loop] - addresses[0]; } /* Build the derived datatype for the items to pass "pointer_to_new_mpi_type" is the new "struct" data type containing 3 floats, 1 int, and an array of 6 ints */ MPI_Type_struct(elements,blocks,disp,type_of_data,&pointer_to_new_mpi_type); MPI_Type_commit(&pointer_to_new_mpi_type); /* Root contains the elements. Send them to other processes */ if (myrank==0) { // Send variable x, the first in the "struct". // "pointer_to_new_mpi_type" will include all the other variables too MPI_Send(&x,1,pointer_to_new_mpi_type,1,0,MPI_COMM_WORLD); } else { /* Non-root processes receive the variables and print them */ MPI_Recv(&x,1,pointer_to_new_mpi_type,0,0,MPI_COMM_WORLD,&status); printf("In process with rank %d\n",myrank); printf("\tx ==> %f y ==> %f z ==> %f a ==> %d\n",x,y,z,a); for(loop=0; loop < elements;loop++) { printf("\tb[%d]==> %d\n",loop,b[loop]); } } /* finish up */ MPI_Type_free(&pointer_to_new_mpi_type); MPI_Finalize(); return 0; } /* cc structMPI.c mpirun -np 2 a.out Example of sending multiple variables, of various types, to other processes. In process with rank 1 x ==> 10.000000 y ==> 20.000000 z ==> 30.000000 a ==> 9 b[0]==> 3 b[1]==> 4 b[2]==> 5 b[3]==> 6 b[4]==> 7 */