Rookie HPC

User-datatypes

C | FORTRAN-legacy | FORTRAN-2008

MPI_Type_create_hindexed

Definition

MPI_Type_create_hindexed stands for heterogeneous indexed; it is the version of MPI_Type_indexed where the displacements are expressed in bytes, and not in number of elements. Other ways to create a datatype are MPI_Type_contiguous, MPI_Type_vector, MPI_Type_create_hvector, MPI_Type_indexed, MPI_Type_create_indexed_block, MPI_Type_create_hindexed_block, MPI_Type_create_struct, MPI_Type_create_subarray, MPI_Type_create_darray.

Copy

Feedback

int MPI_Type_create_hindexed(int block_count,
                             int* block_lengths,
                             MPI_Aint* displacements,
                             MPI_Datatype old_datatype,
                             MPI_Datatype* new_datatype);

Parameters

block_count
The number of blocks to create.
block_lengths
Array containing the length of each block.
displacements
Array containing the displacement for each block, expressed in bytes. The displacement is the distance between the start of the MPI datatype created and the start of the block. It is different from the stride used in MPI_Type_vector for instance, where it expresses the distance between the start of a block to the next.
old_datatype
The datatype making the element used as unit.
new_datatype
The variable in which store the datatype created.

Returned value

The error code returned from the MPI heterogeneous indexed datatype creation.

MPI_SUCCESS
The routine successfully completed.

Example

Copy

Feedback

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

/**
 * @brief Illustrates how to create a heterogeneous indexed MPI datatype.
 * @details This program is meant to be run with 2 processes: a sender and a
 * receiver. These two MPI processes will exchange a message made of six
 * integers. On the sender, that message is in fact the lower triangle of an
 * array it holds, which will be represented by an MPI indexed type.
 *
 *
 *     Full array          What we want
 *                            to send
 * +-----+-----+-----+  +-----+-----+-----+
 * |  0  |  1  |  2  |  |  0  |  -  |  -  |
 * +-----+-----+-----+  +-----+-----+-----+
 * |  3  |  4  |  5  |  |  3  |  4  |  -  |
 * +-----+-----+-----+  +-----+-----+-----+
 * |  6  |  7  |  8  |  |  6  |  7  |  8  |
 * +-----+-----+-----+  +-----+-----+-----+
 *
 * How to extract the lower triangle with a heterogeneous indexed type:
 *
 *   
 *        +---------------------------- displacement for
 *        |                          block 2: 6 sizeof(int)
 *        |                                   |
 *        +---------- displacement for        |
 *        |        block 2: 3 sizeof(int)     |
 *        |                 |                 |
 *  displacement for        |                 |
 *    block 1: 0            |                 |
 *        |                 |                 |
 *        V                 V                 V
 *        +-----+-----+-----+-----+-----+-----+-----+-----+-----+
 *        |  0  |  -  |  -  |  3  |  4  |  -  |  6  |  7  |  8  |
 *        +-----+-----+-----+-----+-----+-----+-----+-----+-----+
 *         <--->             <--------->       <--------------->
 *        block 1              block 2              block 3
 *       1 element            2 elements           3 elements
 * 
 * Element: MPI_INT
 **/
int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);

    // Get the number of processes and check only 2 processes are used
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    if(size != 2)
    {
        printf("This application is meant to be run with 2 processes.\n");
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
    }

    // Get my rank and do the corresponding job
    enum rank_roles { SENDER, RECEIVER };
    int my_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    switch(my_rank)
    {
        case SENDER:
        {
            // Create the datatype
            MPI_Datatype triangle_type;
            int lengths[3] = { 1, 2, 3 };
            MPI_Aint displacements[3] = { 0, 3 * sizeof(int), 6 * sizeof(int) };
            MPI_Type_create_hindexed(3, lengths, displacements, MPI_INT, &triangle_type);
            MPI_Type_commit(&triangle_type);

            // Send the message
            int buffer[3][3] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
            printf("MPI process %d sends values:\n%d\n%d %d\n%d %d %d\n", my_rank, buffer[0][0], buffer[1][0], buffer[1][1], buffer[2][0], buffer[2][1], buffer[2][2]);
            MPI_Send(buffer, 1, triangle_type, RECEIVER, 0, MPI_COMM_WORLD);
            break;
        }
        case RECEIVER:
        {
            // Receive the message
            int received[6];
            MPI_Recv(&received, 6, MPI_INT, SENDER, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            printf("MPI process %d received values:\n%d\n%d %d\n%d %d %d\n", my_rank, received[0], received[1], received[2], received[3], received[4], received[5]);
            break;
        }
    }

    MPI_Finalize();

    return EXIT_SUCCESS;
}