The following examples illustrate the use of derived datatypes.
Example
Send and receive a section of a 3D array.
REAL a(100,100,100), e(9,9,9) INTEGER oneslice, twoslice, threeslice, sizeofreal, myrank, ierr INTEGER status(MPI_STATUS_SIZE) C extract the section a(1:17:2, 3:11, 2:10) C and store it in e(:,:,:). CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr) CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr) C create datatype for a 1D section CALL MPI_TYPE_VECTOR( 9, 1, 2, MPI_REAL, oneslice, ierr) C create datatype for a 2D section CALL MPI_TYPE_HVECTOR(9, 1, 100*sizeofreal, oneslice, twoslice, ierr) C create datatype for the entire section CALL MPI_TYPE_HVECTOR( 9, 1, 100*100*sizeofreal, twoslice, threeslice, ierr) CALL MPI_TYPE_COMMIT( threeslice, ierr) CALL MPI_SENDRECV(a(1,3,2), 1, threeslice, myrank, 0, e, 9*9*9, MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
Copy the (strictly) lower triangular part of a matrix.
Example
Transpose a matrix.
REAL a(100,100), b(100,100) INTEGER row, xpose, sizeofreal, myrank, ierr INTEGER status(MPI_STATUS_SIZE) C transpose matrix a onto b CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr) CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr) C create datatype for one row CALL MPI_TYPE_VECTOR( 100, 1, 100, MPI_REAL, row, ierr) C create datatype for matrix in row-major order CALL MPI_TYPE_HVECTOR( 100, 1, sizeofreal, row, xpose, ierr) CALL MPI_TYPE_COMMIT( xpose, ierr) C send matrix in row-major order and receive in column major order CALL MPI_SENDRECV( a, 1, xpose, myrank, 0, b, 100*100, MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
Another approach to the transpose problem:
REAL a(100,100), b(100,100) INTEGER disp(2), blocklen(2), type(2), row, row1, sizeofreal INTEGER myrank, ierr INTEGER status(MPI_STATUS_SIZE) CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr) C transpose matrix a onto b CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr) C create datatype for one row CALL MPI_TYPE_VECTOR( 100, 1, 100, MPI_REAL, row, ierr) C create datatype for one row, with the extent of one real number disp(1) = 0 disp(2) = sizeofreal type(1) = row type(2) = MPI_UB blocklen(1) = 1 blocklen(2) = 1 CALL MPI_TYPE_STRUCT( 2, blocklen, disp, type, row1, ierr) CALL MPI_TYPE_COMMIT( row1, ierr) C send 100 rows and receive in column major order CALL MPI_SENDRECV( a, 100, row1, myrank, 0, b, 100*100, MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
We manipulate an array of structures.
Example
The same manipulations as in the previous example, but use absolute
addresses in datatypes.
Example
Handling of unions.
Example
This
example shows how a datatype can be decoded. The routine
printdatatype prints out the elements of the datatype. Note the use
of MPI_Type_free for datatypes that are not predefined.
/* Example of decoding a datatype. Returns 0 if the datatype is predefined, 1 otherwise */ #include <stdio.h> #include <stdlib.h> #include "mpi.h" int printdatatype( MPI_Datatype datatype ) { int *array_of_ints; MPI_Aint *array_of_adds; MPI_Datatype *array_of_dtypes; int num_ints, num_adds, num_dtypes, combiner; int i; MPI_Type_get_envelope( datatype, &num_ints, &num_adds, &num_dtypes, &combiner ); switch (combiner) { case MPI_COMBINER_NAMED: printf( "Datatype is named:" ); /* To print the specific type, we can match against the predefined forms. We can NOT use a switch statement here We could also use MPI_TYPE_GET_NAME if we prefered to use names that the user may have changed. */ if (datatype == MPI_INT) printf( "MPI_INT\n" ); else if (datatype == MPI_DOUBLE) printf( "MPI_DOUBLE\n" ); ... else test for other types ... return 0; break; case MPI_COMBINER_STRUCT: case MPI_COMBINER_STRUCT_INTEGER: printf( "Datatype is struct containing" ); array_of_ints = (int *)malloc( num_ints * sizeof(int) ); array_of_adds = (MPI_Aint *) malloc( num_adds * sizeof(MPI_Aint) ); array_of_dtypes = (MPI_Datatype *) malloc( num_dtypes * sizeof(MPI_Datatype) ); MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); printf( " %d datatypes:\n", array_of_ints[0] ); for (i=0; i<array_of_ints[0]; i++) { printf( "blocklength %d, displacement %ld, type:\n", array_of_ints[i+1], array_of_adds[i] ); if (printdatatype( array_of_dtypes[i] )) { /* Note that we free the type ONLY if it is not predefined */ MPI_Type_free( &array_of_dtypes[i] ); } } free( array_of_ints ); free( array_of_adds ); free( array_of_dtypes ); break; ... other combiner values ... default: printf( "Unrecognized combiner type\n" ); } return 1; }