Как исправить недопустимые аргументы при создании производных типов данных MPI


У меня есть один structure xyz , как указано ниже struct xyz { char a; int32_t b; char c[50]; uint32_t d; uchar e[10];}

Мне нужно передать его, поэтому я использовал MPI_Bcast (), где мне требовался тип данных MPI, соответствующий struct xyz для этого я использовал функцию MPI_Type_creat_struct() для создания нового типа данных MPI как MPI_Datatype MPI_my_new_datatype, oldtypes[4];, где я использовал типы данных MPI, соответствующие указанным выше элементам структуры datatype как следующие

oldtypes[4] = {MPI_CHAR, MPI_INT, MPI_UNSIGNED, MPI_UNSIGNED_CHAR}; и чтобы создать новый тип данных, я использовал следующие аргументы в функции..

MPI_Type_create_struct(4,blockcounts, offsets, oldtypes, &MPI_my_new_datatype); MPI_Type_commit(&MPI_my_new_datatype);

Теперь он компилируется, но выдает ошибку времени выполнения как под:: * произошла ошибка в MPI_Type_create_structна коммуникаторе MPI_COMM_WORLD MPI_ERR_ARG: недопустимый аргумент другого рода MPI_ERRORS_ARE_FATAL (до свидания).

Может ли кто-нибудь выяснить, в чем проблема?
1 2

1 ответ:

Вы не можете "связывать" подобные типы подобным образом. Каждая область должна рассматриваться отдельно, и их 5, а не 4.

Также обратите внимание, что, в общем, это хорошая идея, чтобы на самом деле "измерить" смещения, а не выводить их.

Следующие работы:

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

struct xyz_t {
    char a; int32_t b; char c[50]; uint32_t d; unsigned char e[10];
};

int main(int argc, char **argv) {
    int rank, size, ierr;
    MPI_Datatype oldtypes[5] = {MPI_CHAR, MPI_INT, MPI_CHAR, MPI_UNSIGNED, MPI_UNSIGNED_CHAR};
    int blockcounts[5] = {1, 1, 50, 1, 10};
    MPI_Datatype my_mpi_struct;
    MPI_Aint offsets[5];

    struct xyz_t old, new;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    /* find offsets */

    offsets[0] = (char*)&(old.a) - (char*)&old;
    offsets[1] = (char*)&(old.b) - (char*)&old;
    offsets[2] = (char*)&(old.c) - (char*)&old;
    offsets[3] = (char*)&(old.d) - (char*)&old;
    offsets[4] = (char*)&(old.e) - (char*)&old;

    MPI_Type_create_struct(5, blockcounts, offsets, oldtypes, &my_mpi_struct);
    MPI_Type_commit(&my_mpi_struct);
    if (rank == 0) {
        old.a = 'a';
        old.b = (int)'b';
        strcpy(old.c,"This is field c");
        old.d = (unsigned int)'d';
        strcpy(old.e,"Field e");

        MPI_Send(&old, 1, my_mpi_struct, 1, 1, MPI_COMM_WORLD);
    } else if (rank == 1) {
        MPI_Status status;
        MPI_Recv(&new, 1, my_mpi_struct, 0, 1, MPI_COMM_WORLD, &status);
        printf("new.a = %c\n", new.a);
        printf("new.b = %d\n", new.b);
        printf("new.e = %s\n", new.e);
    }

    MPI_Type_free(&my_mpi_struct);
    MPI_Finalize();

    return 0;
}

Бег:

$ mpirun -np 2 ./struct
new.a = a
new.b = 98
new.e = Field e

Обновлено : как указывает Дэйв Гуделл ниже, расчеты смещения лучше выполнять как

#include <stddef.h>
/* ... */

offsets[0] = offsetof(struct xyz_t,a);
offsets[1] = offsetof(struct xyz_t,b);
offsets[2] = offsetof(struct xyz_t,c);
offsets[3] = offsetof(struct xyz_t,d);
offsets[4] = offsetof(struct xyz_t,e);

И если ваш MPI поддерживает его (большинство должно, хотя OpenMPI был медленным с некоторыми типами MPI2. 2) MPI_UNSIGNED следует заменить на MPI_UINT32