Introduction to User-Defined Datatypes



next up previous contents
Next: Datatype Constructors Up: User-Defined Datatypes and Previous: Introduction

Introduction to User-Defined Datatypes

 

All MPI communication functions take a datatype argument. In the simplest case this will be a primitive type, such as an integer or floating-point number. An important and powerful generalization results by allowing user-defined (or ``derived'') types wherever the primitive types can occur. These are not ``types'' as far as the programming language is concerned. They are only ``types'' in that MPI is made aware of them through the use of type-constructor functions, and they describe the layout, in memory, of sets of primitive types. Through user-defined types, MPI supports the communication of complex data structures such as array sections and structures containing combinations of primitive datatypes. Example gif shows how a user-defined datatype is used to send the upper-triangular part of a matrix, and Figure gif diagrams the memory layout represented by the user-defined datatype. derived datatype constructor

 


Figure: A diagram of the memory cells represented by the user-defined datatype upper. The shaded cells are the locations of the array that will be sent.

Derived datatypes are constructed from basic datatypes using the constructors described in Section gif. The constructors can be applied recursively.

A derived datatype is an opaque object that specifies two things:

o A sequence of primitive datatypes and,
o A sequence of integer (byte) displacements. 
The displacements are not required to be positive, distinct, or in increasing order. Therefore, the order of items need not coincide with their order in memory, and an item may appear more than once. We call such a pair of sequences (or sequence of pairs) a type map. The sequence of primitive datatypes (displacements ignored) is the type signature of the datatype. type maptype signature derived datatype, mapderived datatype, signature

Let

be such a type map, where type are primitive types, and disp are displacements. Let

be the associated type signature. This type map, together with a base address buf, specifies a communication buffer: the communication buffer that consists of n entries, where the i-th entry is at address buf + desp and has type type . A message assembled from a single type of this sort will consist of n values, of the types defined by Typesing .

A handle to a derived datatype can appear as an argument in a send or receive operation, instead of a primitive datatype argument. The operation MPI_SEND(buf, 1, datatype,...) will use the send buffer defined by the base address buf and the derived datatype associated with datatype. It will generate a message with the type signature determined by the datatype argument. MPI_RECV(buf, 1, datatype,...) will use the receive buffer defined by the base address buf and the derived datatype associated with datatype.

Derived datatypes can be used in all send and receive operations including collective. We discuss, in Section gif, the case where the second argument count has value > 1.

The primitive datatypes presented in Section gif are special cases of a derived datatype, and are predefined. Thus, MPI_INT is a predefined handle to a datatype with type MPI_INT map {(int,0)}, with one entry of type int and displacement zero. The other primitive datatypes are similar.

The extent of a datatype is defined to be the span from the first byte to the last byte occupied by entries in this datatype, rounded up to satisfy alignment requirements. extentderived datatype, extent That is, if

then

extent(Typeman) = ub(Typemap) - lb(Typemap).
where j = 0,-----,n-1. lb is the lower bound and ub is the upper bound of the datatype. lower boundderived datatype, lower bound upper boundderived datatype, upper bound If type requires alignment to a byte address that is a multiple of k , then a is the least nonnegative increment needed to round extent(Typemap) to the next multiple of max k . (The definition of extent is expanded in Section gif.)

The following functions return information on datatypes.

MPI_TYPE_EXTENT(datatype, extent)

   IN     datatype             datatype
   OUT    extent               datatype extent
MPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent)

MPI_TYPE_EXTENT(DATATYPE, EXTENT, IERROR)INTEGER DATATYPE, EXTENT, IERROR

MPI_TYPE_EXTENT returns the extent of a datatype. In addition to its use with derived datatypes, it can be used to inquire about the extent of primitive datatypes. For example, MPI_TYPE_EXTENT(MPI_INT, extent) will return in extent the size, in bytes, of an int - the same value that would be returned by the C call sizeof(int).

MPI_Type_size(MPI_Datatype datatype, int *size)

MPI_TYPE_SIZE(DATATYPE, SIZE, IERROR)INTEGER DATATYPE, SIZE, IERROR

MPI_TYPE_SIZE returns the total size, in bytes, of the entries in the type signature associated with datatype; that is, the total size of the data in a message that would be created with this datatype. Entries that occur multiple times in the datatype are counted with their multiplicity. For primitive datatypes, this function returns the same information as MPI_TYPE_EXTENT.



next up previous contents
Next: Datatype Constructors Up: User-Defined Datatypes and Previous: Introduction



Jack Dongarra
Fri Sep 1 06:16:55 EDT 1995