我有以下结构.
typedef struct
{
int *Ai;
double *Ax;
int nz;
}column;
Run Code Online (Sandbox Code Playgroud)
我想用MPI_Send和转移这个结构MPI_Receive.如何MPI_Datatype为此结构创建?
Hri*_*iev 12
MPI旨在使用结构数组而不是数组结构.
该MPI_Hindexed@suszterpatt提出,是一个可怕的黑客.它只允许您发送结构类型的一个元素,并且只发送用于定义MPI数据类型的元素.对于相同结构类型的其他变量,主要保证计算的偏移量是错误的.除了Hindexed类型,对所有元素使用同一个MPI数据类型,因此不允许您发送整数和双精度数.
明智的做法是将程序转换为使用结构数组:
typedef struct
{
int i;
double z;
} point;
typedef struct
{
point *A;
int nz;
} column;
Run Code Online (Sandbox Code Playgroud)
现在,您可以创建一个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, ...);
Run Code Online (Sandbox Code Playgroud)
这首先创建一个point_struct描述结构成员布局的MPI数据类型,但不考虑最后的任何填充,因此不能用于可靠地发送此类结构的数组.因此,point_type使用创建具有正确范围的第二种数据类型MPI_Type_create_resized.
在接收方,您将查看消息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);
Run Code Online (Sandbox Code Playgroud)
如果代码更改是不可能的,您仍然可以在发送之前完成转换结构的中间步骤,这个过程通常称为(un-)编组.在你的情况下做这样的事情(我假设你在两个Ai和Ax在nz字段中存储数组元素的数量):
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);
Run Code Online (Sandbox Code Playgroud)
在接收方,你必须做相反的事情:分配一个足够大的缓冲区,它可以保存结构,接收消息,然后进行相反的转换.
再一次,您不需要传输实际值,nz因为它可以使用消息的长度轻松提取MPI_Get_count.
向另一台机器发送指针毫无意义(没有双关语).由于虚拟寻址,指针可能指向接收机器上的无效内存位置,即使没有,您实际上也没有发送它指向的数据.
但是,通过正确使用MPI_Address()和MPI_Hindexed数据类型,可以描述数据的内存布局(我假设您的指针指向动态数组).例如,如果Ai指向3 int秒,并Ax指向5 double秒,则需要一个Hindexed包含3个块的类型:3 MPI_INT秒,5 MPI_DOUBLE秒和1 MPI_INT,并使用获取的偏移量MPI_Address().
如果更改要发送的项目数或完全重新分配数组,请不要忘记重新定义并重新提交数据类型.如果您要发送多个结构,则必须为每个结构定义并提交此数据类型,因为您的MPI数据类型特定于这些结构的一个特定实例.
另外请记住,如果要重新创建原始结构,则必须在接收端执行类似的棘手解包.
| 归档时间: |
|
| 查看次数: |
7226 次 |
| 最近记录: |