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