Rookie HPC

About

Docs

Tools

Tests

MPI_Type_create_struct

Definition

MPI_Type_create_struct is the most flexible routine to create an MPI datatype. It builds the MPI_Datatype as a sequence of blocks: each block being made by replicating an existing MPI_Datatype a certain number of times. The flexibility is that, for each block, the number of replicates to use, the MPI datatype to replicate and the displacement to apply is specified separately. Other ways to create a datatype are MPI_Type_contiguous, MPI_Type_vector, MPI_Type_create_hvector, MPI_Type_indexed, MPI_Type_create_hindexed, MPI_Type_create_indexed_block, MPI_Type_create_hindexed_block, MPI_Type_create_subarray, MPI_Type_create_darray.

Copy

Feedback

int MPI_Type_create_struct(int block_count,
                           int* block_lengths,
                           MPI_Aint* block_displacements,
                           MPI_Datatype* block_types,
                           MPI_Datatype* new_type);

Parameters

block_count
The number of blocks to create.
block_lengths
Array containing the length of each block.
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.
block_types
Array containing the MPI datatypes to replicate to make each block.
new_type
The variable in which store the datatype created.

Returned value

MPI_SUCCESS
The routine successfully completed.

Example

Copy

Feedback

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

/**
 * @brief Illustrates how to create an 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 a
 * structure representing a person.
 *
 * Structure of a person:
 * - age: int
 * - height: double
 * - name: char[10]
 *
 * How to represent such a structure with an MPI struct:
 *   
 *        +------------------ displacement for
 *        |         block 2: sizeof(int) + sizeof(double)
 *        |                         |
 *        +----- displacement for   |
 *        |    block 2: sizeof(int) |
 *        |            |            |
 *  displacement for   |            |
 *    block 1: 0       |            |
 *        |            |            |
 *        V            V            V
 *        +------------+------------+------------+
 *        |    age     |   height   |    name    |
 *        +------------+------------+------------+
 *         <----------> <----------> <---------->
 *            block 1      block 2      block 3
 *           1 MPI_INT  1 MPI_DOUBLE  10 MPI_CHAR
 **/

struct person_t
{
    int age;
    double height;
    char name[10];
};

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);
    }

    // Create the datatype
    MPI_Datatype person_type;
    int lengths[3] = { 1, 1, 10 };
    const MPI_Aint displacements[3] = { 0, sizeof(int), sizeof(int) + sizeof(double) };
    MPI_Datatype types[3] = { MPI_INT, MPI_DOUBLE, MPI_CHAR };
    MPI_Type_create_struct(3, lengths, displacements, types, &person_type);
    MPI_Type_commit(&person_type);

    // 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:
        {
            // Send the message
            struct person_t buffer;
            buffer.age = 20;
            buffer.height = 1.83;
            strncpy(buffer.name, "Tom", 9);
            buffer.name[9] = '\0';
            MPI_Request request;
            printf("MPI process %d sends person:\n\t- age = %d\n\t- height = %f\n\t- name = %s\n", my_rank, buffer.age, buffer.height, buffer.name);
            MPI_Send(&buffer, 1, person_type, RECEIVER, 0, MPI_COMM_WORLD);
            break;
        }
        case RECEIVER:
        {
            // Receive the message
            struct person_t received;
            MPI_Recv(&received, 1, person_type, SENDER, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            printf("MPI process %d received person:\n\t- age = %d\n\t- height = %f\n\t- name = %s\n", my_rank, received.age, received.height, received.name);
            break;
        }
    }

    MPI_Finalize();

    return EXIT_SUCCESS;
}