It is often convenient to define explicitly the lower bound and upper bound of a type map, and override the definition given on page Lower-Bound and Upper-Bound Markers . This allows one to define a datatype that has ``holes'' at its beginning or its end, or a datatype with entries that extend above the upper bound or below the lower bound. Examples of such usage are provided in Section Examples . Also, the user may want to overide the alignment rules that are used to compute upper bounds and extents. E.g., a C compiler may allow the user to overide default alignment rules for some of the structures within a program. The user has to specify explicitly the bounds of the datatypes that match these structures.
To achieve this, we add two additional conceptual datatypes, lb_marker and ub_marker, that represent the lower bound and upper bound of a datatype. These conceptual datatypes occupy no space (extent(mpiublblb_marker) = extent(mpiublbub_marker) =0) . They do not affect the size or count of a datatype, and do not affect the content of a message created with this datatype. However, they do affect the definition of the extent of a datatype and, therefore, affect the outcome of a replication of this datatype by a datatype constructor.
Example
A call to
MPI_TYPE_CREATE_RESIZED(MPI_INT, -3, 9, type1)
creates a new datatype that has an
extent of 9 (from -3 to 5, 5 included), and contains an integer at
displacement 0. This is the datatype defined by the typemap
{( lb_marker, -3), (int, 0), ( ub_marker, 6)}.
If this type is replicated twice by a call to
MPI_TYPE_CONTIGUOUS(2, type1, type2) then the newly created
type can
be described by the typemap
{( lb_marker, -3), (int, 0), (int,9), ( ub_marker, 15)}.
(An entry of type
ub_marker
can be deleted if there is another entry of type ub_marker with a
higher
displacement; an entry of type lb_marker can be deleted if there
is another
entry of type lb_marker with a lower displacement.)
In general, if Typemap = { (type0 , disp0 ) , ... , (typen-1 , dispn-1) } , then the lower bound of Typemap is defined to be
Similarly, the upper bound of Typemap is defined to be
Then
extent(Typemap) = ub(Typemap) - lb(Typemap)
If typei requires alignment to a byte address that is a multiple of ki, then is the least non-negative increment needed to round extent(Typemap) to the next multiple of . In Fortran, it is implementation dependent whether the MPI implementation computes the alignments ki according to the alignments used by the compiler in common blocks, SEQUENCE derived types, BIND(C) derived types, or derived types that are neither SEQUENCE nor BIND(C).
The formal definitions given for the various datatype constructors apply now, with the amended definition of extent.
Rationale.
Before Fortran 2003, MPI_TYPE_CREATE_STRUCT could be applied to Fortran common blocks and
SEQUENCE derived types. With Fortran 2003, this list was extended by BIND(C) derived types
and MPI implementors have implemented the alignments ki differently, i.e., some based on
the alignments used in SEQUENCE derived types, and others according to BIND(C) derived types.
( End of rationale.)
Advice
to implementors.
In Fortran, it is generally recommended to use BIND(C) derived types instead of
common blocks or SEQUENCE derived types. Therefore it is recommended to calculate the
alignments ki based on BIND(C) derived types.
( End of advice to implementors.)
Advice to users.
Structures combining different basic datatypes should be defined so that there will be no gaps based on alignment rules. If such a datatype is used to create an array of structures, users should also avoid an alignment-gap at the end of the structure. In MPI communication, the content of such gaps would not be communicated into the receiver's buffer. For example, such an alignment-gap may occur between an odd number of floats or REALs before a double or DOUBLE PRECISION data. Such gaps may be added explicitly to both the structure and the MPI derived datatype handle because the communication of a contiguous derived datatype may be significantly faster than the communication of one that is non-contiguous because of such alignment-gaps.
Example: Instead of
TYPE, BIND(C) :: my_data REAL, DIMENSION(3) :: x ! there may be a gap of the size of one REAL ! if the alignment of a DOUBLE PRECISION is ! two times the size of a REAL DOUBLE PRECISION :: p END TYPEone should define
TYPE, BIND(C) :: my_data REAL, DIMENSION(3) :: x REAL :: gap1 DOUBLE PRECISION :: p END TYPEand also include gap1 in the matching MPI derived datatype. It is required that all processes in a communication add the same gaps, i.e., defined with the same basic datatype. Both the original and the modified structures are portable, but may have different performance implications for the communication and memory accesses during computation on systems with different alignment values.
In principle, a compiler may define an additional alignment rule
for structures, e.g., to use at least 4 or 8 byte alignment, although
the content may have a maxi ki alignment less than this structure
alignment. To maintain portability, users should
always resize structure derived datatype handles
if used in an array of structures, see the Example in
Section Fortran Derived Types
.
( End of advice to users.)