Как исправить неверные аргументы при создании типов данных, полученных из MPI - PullRequest
2 голосов
/ 24 января 2012

У меня есть один 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, соответствующие указанным выше типам элементов структуры, следующим образом

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 Ответ

3 голосов
/ 24 января 2012

Вы не можете "связать" подобные типы таким образом. Каждое поле должно быть адресовано отдельно, и их 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

...