为包含指针的结构创建 MPI_Datatype

标签 c mpi

我有以下结构。

typedef struct
{
 int *Ai;
 double *Ax;
 int nz;
}column;

我想使用 MPI_SendMPI_Receive 传输这个结构。如何为此结构创建 MPI_Datatype

最佳答案

MPI 旨在处理结构数组而不是数组结构。

@suszterpatt 提出的 MPI_Hindexed 是一个可怕的 hack。它只允许您发送结构类型的一个元素,并且只允许发送用于定义 MPI 数据类型的元素。对于相同结构类型的其他变量,大多数情况下可以保证计算出的偏移量是错误的。此外,Hindexed 类型对所有元素使用同一种 MPI 数据类型,因此不允许您同时发送 int 和 double。

明智的做法是将您的程序转换为使用结构数组:

 typedef struct
 {
    int i;
    double z;
 } point;

 typedef struct
 {
    point *A;
    int nz;
 } column;

现在您可以创建一个 MPI 结构化类型 point_type 并使用它发送该类型的 nz 元素,将 column.A 作为缓冲区地址:

 int lens[3];
 MPI_Aint base, disps[2];
 MPI_Datatype oldtypes[2], point_struct, point_type;

 MPI_Get_address(&point, disps);
 MPI_Get_address(&point.z, disps+1);
 base = disps[0];

 lens[0] = 1; disps[0] = MPI_Aint_diff(disps[0], base); oldtypes[0] = MPI_INT;
 lens[1] = 1; disps[1] = MPI_Aint_diff(disps[1], base); oldtypes[1] = MPI_DOUBLE;
 MPI_Type_create_struct(2, lens, disps, oldtypes, &point_struct);
 MPI_Type_create_resized(point_struct, 0, sizeof(point), &point_type);
 MPI_Type_commit(&point_type);

 MPI_Send(column.A, column.nz, point_type, ...);

这首先创建了一个描述结构成员布局的 MPI 数据类型 point_struct,但不考虑末尾的任何填充,因此不能用于可靠地发送此类结构的数组。因此,使用 MPI_Type_create_resized 创建具有正确范围的第二个数据类型 point_type

在接收方,您可以使用 MPI_Probe 查看消息,使用 MPI_Get_count 提取元素的数量,类型为 point_type(即直接进入nz字段),分配A字段,在MPI_Recv中使用它来接收nz元素:

 MPI_Status status;
 MPI_Probe(source, tag, comm, &status);
 MPI_Get_count(&status, point_type, &column.nz);
 if (nz == MPI_UNDEFINED)
   ... non-integral message was received, do something
 column.A = (point *)malloc(column.nz*sizeof(point));
 MPI_Recv(column.A, column.nz, point_type, source, tag, comm, MPI_STATUS_IGNORE);

如果无法更改代码,您仍然可以在发送结构之前完成转换结构的中间步骤,这个过程通常称为(非)编码。在你的情况下做这样的事情(我假设你将数组元素的数量存储在 AiAxnz 字段中):

 point *temp = (point *)malloc(nz*sizeof(point));
 for (int i = 0; i < column.nz; i++)
 {
   temp[i].i = column.Ai[i];
   temp[i].z = column.Az[i];
 }
 MPI_Send(temp, nz, point_type, ...);
 free(temp);

在接收端你必须做相反的事情:分配一个足够大的缓冲区来容纳这个结构,在其中接收消息然后做相反的转换。

再一次,您不需要传输 nz 的实际值,因为可以使用 MPI_Get_count 从消息的长度中轻松提取它。

关于为包含指针的结构创建 MPI_Datatype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10419990/

相关文章:

c - 我需要根据文件上有多少元素使用 X 结构,可以吗?

c - 请验证我对这个与结构相关的事情的想法是否正确

c - MPI 矩阵乘法

c - 当 MPI_Bcast 中的 root 是随机的时会发生什么

python - 使用 mpifort 编译程序时包含的模块出现问题

c++ - 使用 MPI 划分工作

将有符号转换为无符号时,C 编译器能否更改位表示?

C语言中的CLOCKS_PER_SEC找到time.h库

c - 调用 C/Fortran 例程时忽略 evalWithTimeout?

mpi - 使用 MPI_File_open 时出现段错误