82. Examples


Up: Derived Datatypes Next: Pack and Unpack Previous: Decoding a Datatype

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; 
} 



Up: Derived Datatypes Next: Pack and Unpack Previous: Decoding a Datatype


Return to MPI-2.2 Standard Index
Return to MPI Forum Home Page

(Unofficial) MPI-2.2 of September 4, 2009
HTML Generated on September 10, 2009