我有n个workers
,1个master
(等级0),并且需要通过MPI从n个workers
到master
发送消息。消息格式是可变长度向量(float *dta
)和恒定大小的标头struct { int32_t x, int32_t y } dtaHdr
。
主控器仅遍历传入的结果并对其进行处理。能够将哪个dtaHdr
与哪个dta
关联起来很重要。
我知道该怎么做
MPI_Datatype
创建dtaHdr
,然后通过P2P MPI_Send
/ MPI_Recv
发送。MPI_Float
/ MPI_Send
发送任何数据类型(例如MPI_Recv
)的可变长度向量。问题是我不知道如何结合这两种方法。
我知道我可以做到:
master
上的数据。对于两条消息,我看不到如何始终简单地获取主服务器上传入消息的标头和数据的方法。即两个worker
可以向master
发送hdr和数据消息,并且它们可能变得交错。 (即使阅读了MPI规范,我也不确定TBH的订购保证是什么。)MPI_Byte
数组中,并将其作为二进制Blob实质发送。
我的问题:我如何MPI惯用地发送一条可识别的逻辑消息,该消息既包含一种类型的恒定大小的标头,又包含某种第二类型的可变大小的矢量。
答案 0 :(得分:1)
该程序使用MPI_Pack
和MPI_Unpack
在同一封邮件中发送两种不同的类型:
#include <mpi.h>
#include <stdio.h>
#define ARRAY_SIZE(array) \
(sizeof(array) / sizeof(array[0]))
struct data_header {
int32_t x;
int32_t y;
};
MPI_Datatype dt_header;
MPI_Datatype dt_vector;
void sendmsg(void) {
struct data_header header = { 1, 2 };
float example[] = { 1.0, 2.0, 3.0, 4.0 };
char buffer[4096];
int position;
MPI_Pack(&header, 1, dt_header, buffer, sizeof(buffer), &position, MPI_COMM_WORLD);
MPI_Pack(example, 1, dt_vector, buffer, sizeof(buffer), &position, MPI_COMM_WORLD);
MPI_Send(buffer, position, MPI_PACKED, 0, 0, MPI_COMM_WORLD);
}
void recvmsg(void) {
struct data_header header;
float example[4];
char buffer[4096];
int position = 0;
MPI_Recv(buffer, sizeof(buffer), MPI_PACKED, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Unpack(buffer, sizeof(buffer), &position, &header, 1, dt_header, MPI_COMM_WORLD);
MPI_Unpack(buffer, sizeof(buffer), &position, example, 1, dt_vector, MPI_COMM_WORLD);
printf("x = %d, y = %d\n", header.x, header.y);
for (int index = 0; index < ARRAY_SIZE(example); index++) {
printf("%f ", example[index]);
}
printf("\n");
}
int main(void) {
int world_size;
int world_rank;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Type_contiguous(2, MPI_INT, &dt_header);
MPI_Type_commit(&dt_header);
MPI_Type_contiguous(4, MPI_FLOAT, &dt_vector);
MPI_Type_commit(&dt_vector);
if (0 == world_rank) {
recvmsg();
}
else {
sendmsg();
}
MPI_Finalize();
return 0;
}
输出
x = 1, y = 2
1.000000 2.000000 3.000000 4.000000
这实际上只是概念验证代码。希望它将帮助您找到所需的解决方案。
注意
此代码不进行错误检查,因此不应在生产环境中使用。