创建MPI_Datatype包含指针的结构 [英] Creating an MPI_Datatype for a structure containing pointers
问题描述
我有以下的结构。
typedef struct
{
int *Ai;
double *Ax;
int nz;
}column;
我想用 MPI_SEND
和 MPI_Receive
来传递这个结构。如何创建一个 MPI_Datatype
这个结构呢?
I want to transfer this structure using MPI_Send
and MPI_Receive
. How do I create an MPI_Datatype
for this structure?
推荐答案
MPI的设计与阵列的结构,而该结构数组工作。
MPI is designed to work with arrays of structures rather that with structures of arrays.
的 MPI_Hindexed
的@suszterpatt提出的是一个可怕的黑客。它将只允许发送被用来定义在MPI数据类型的结构类型,并且只有元件的一个元件。对于相同的结构类型的其它变量它主要是保证所计算的偏移量将是错误的。除了 Hindexed 类型使用一个和所有元素相同MPI数据类型,因此不允许您发送两个整数和双打。
The MPI_Hindexed
that @suszterpatt proposed is a terrible hack. It will only allow you to send one element of the structure type and only the element that was used to define the MPI data type. For other variables of the same structure type it is mostly guaranteed that the computed offsets will be wrong. Besides Hindexed types use one and the same MPI data type for all elements and thus does not allow you to send both ints and doubles.
的明智的做法是把你的程序使用结构数组:
The wise thing to do is to transform your program to use arrays of structures:
typedef struct
{
int i;
double z;
} point;
typedef struct
{
point *A;
int nz;
} column;
现在,你可以创建一个MPI结构类型 point_type
有三个字段(两个数据字段和一个特殊),并用它来发送新西兰
该类型给人元素 column.A
作为缓冲地址:
Now you can create an MPI structured type point_type
with three fields (two data fields and one special) and use it to send nz
elements of that type giving column.A
as the buffer address:
int lens[3];
MPI_Aint disps[3];
MPI_Datatype oldtypes[3], point_type;
lens[0] = 1; disps[0] = 0; oldtypes[0] = MPI_INT;
lens[1] = 1; disps[1] = &point.z - &point; oldtypes[1] = MPI_DOUBLE;
lens[2] = 1; disps[2] = sizeof(point); oldtypes[2] = MPI_UB;
MPI_Type_create_struct(3, lens, disps, oldtypes, &point_type);
MPI_Type_commit(&point_type);
MPI_Send(column.A, column.nz, point_type, ...);
在MPI结构类型的附加第三个字段设置上限的每个元素(有效的大小),并允许你发送即使编译器已经推出填充在结构上许多连续的结构元素。
The additional third field in the MPI structure type sets the upper bound of each element (effectively its size) and allows you to send many consecutive structure elements even if the compiler has introduced padding in the structure.
在接收端,你会偷看的消息, MPI_PROBE
,提取元素与 MPI_Get_count
与数 point_type
的类型(即径直到新西兰
字段),分配 A
字段,并用它在 MPI_RECV
接收新西兰
元素:
On the receiver side you would peek the message with MPI_Probe
, extract the number of elements with MPI_Get_count
with a type of point_type
(that goes straight to the nz
field), allocate the A
field and use it in MPI_Recv
to receive the nz
elements:
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);
如果是code的变化是不可能的,你仍然可以通过发送之前将您的结构的中间步骤,这个过程通常称为的(非)整编的。在你的情况做这样的事情(我假设你存储在艾
和斧
这两个数组元素的个数在新西兰
字段):
If that code change is impossible you can still go through the intermediate step of transforming your structure before sending it, a process usually called (un-)marshaling. In your case do something like this (I assume that you store the number of array elements in both Ai
and Ax
in the nz
field):
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);
在接收端必须做相反:分配一个足够大的缓冲区,可容纳结构,它收到消息,然后做相反的转化
On the receiver side you must do the opposite: allocate a large enough buffer that can hold the structure, receive the message in it and then do the opposite transformation.
再一次,你不需要传输新西兰
的实际价值,因为它可以使用该消息的长度可以容易地提取 MPI_Get_count
。
Once again, you do not need to transmit the actual value of nz
since it can be easily extracted from the length of the message using MPI_Get_count
.
这篇关于创建MPI_Datatype包含指针的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!