Boundaries and extent of an MPI data type

Content

Assume that we are not that fortunate to have a matrix in row-major order with A.incCol() == 1. In this case, we can construct a data type in two steps:

To do this, we need to understand how MPI interpretes vectors in non-trivial cases. It is obvious if the elements are stored consecutively in memory. In case of a column-major matrix with A.incRow() == 1 the rows are not consecutively in memory. Instead they overlap with offsets.

To understand how MPI sees this, we should return to the definition of a data type as sequence of tuples: \(T = \left\{ (et_1, o_1), (et_2, o_2), \dots, (et_n, o_n) \right\}\).

Assume we have a \(2 \times 3\) matrix in column-major order. The data type \(R\) for the first row would then look as follows: \(R = \left\{ (DOUBLE, 0), (DOUBLE, 16), (DOUBLE, 32) \right\}\). Then we have \(\mbox{lb}(R) = 0\), \(\mbox{ub}(R) = 40\), and \(\mbox{extent}(R) = \mbox{ub}(R) - \mbox{lb}(R) = 40\). If we would combine two such rows to one vector, the absolute offset of the first element of the second row vector would be 40 but actually it starts at 8.

The MPI library allows us to divert from the default by using the function MPI_Type_create_resized:

int MPI_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb,
                            MPI_Aint extent, MPI_Datatype* newtype);

Here lb specifies the new lower boundary \(\mbox{lb}(T)\) and extent specifies \(\mbox{extent}(T)\) in bytes. From this we get implicitly \(\mbox{ub}(T)\). It is permitted to chose an extent in a way where two “consecutively” following objects actually overlap. In the example above of a column-major matrix we could define the extent to be of 8 bytes as the offset between &A(0, 0) and &A(1, 0) is just 8 bytes.

In the trivial case that all elements of a vector are consecutively in memory, we can also use MPI_Type_contiguous:

int MPI_Type_contiguous(int count, MPI_Datatype oldtype,
                        MPI_Datatype* newtype);

Exercise