Layout of struct data types

So far we learnt how to transfer continuous vectors. How would we transfer if there are some gaps or holes in the vectors?

Vector data types

What we learnt so far in the previous subsection and the exercise were more like continuous vectors. Sometimes we would need to communicate vectors with holes that we do not want to be transferred. This implies that we would not send each element but just selected elements or sequence of elements. Therefore the block length and the offset of each can be used to create a stride. When we want to communicate just a portion of a continuous chunk of memory the destination and source may not be the same. Usually, we have one element to receive the results back from the array of cluster. We saw in the previous Pi example how the integrals were collected back, so that we see the complete sums for which we could use such vector data types.

Image courtesy: Rolf Rabenseifner (HLRS)

We use the following routine for vector data types:

int MPI_Type_vector (int count, int blocklength, int stride, MPI_Datatype oldtype, MPI_Datatype *newtype)

The structure of the routine is similar to most we have learnt previously:

• count suggests how many elements
• blocklength is the number of elements per block
• stride is the offset to the next portion of the result
• Datatype – we can have only one data type here and it could be a derived one. Of course, we can communicate a strided array of slots and integers and subsequently we will get a newtype created that can be used in send and receive routines.

Struct data type

So, we could have old types that are of different sizes and then we could combine two old types into a single vector or a block that can be also with holes and these holes will not be communicated. This is a more prevalent way to describe the type instead of doing what we saw earlier. The previous method is not optimal for large numbers of such kinds of arrays. In such cases we use the struct data types, so that communication is executed in the correct way.

The routine for this data type looks like

int MPI_Type_create_struct (int count, int *array_of_blocklengths, MPI_Aint *array_of_displacements, MPI_Datatype *array

This is how memory layout of struct data types could look like with gaps inside that we don’t actually want, but are imposed by the compiler itself or the underlying operating system or hardware processor.

Let’s assume that we have the following parameters:

count = 2array_of_blocklengths = ( 3, 5 )array_of_displacements = ( 0, addr_1 – addr_0 ) array_of_types = ( MPI_INT, MPI_DOUBLE )

In this case the prototype for fixed memory layout of the struct data type would be as follows:

struct buff { int i_val[3]; double d_val[5];}