在一条消息中发送具有常量 header 的可变长度向量
Send variable length vector with constant header in one message
我有 n workers
、1 master
(等级 0),需要通过 MPI 从 n workers
发送消息到 master
。消息格式是可变长度向量 (float *dta
) 和恒定大小 header struct { int32_t x, int32_t y } dtaHdr
.
master 只是循环传入的结果并处理它们。重要的是它能够将哪个 dtaHdr
与哪个 dta
关联起来。
我知道如何:
- 为常量
dtaHdr
创建 MPI_Datatype
并通过 P2P MPI_Send
/MPI_Recv
. 发送
- 通过 P2P
MPI_Send
/MPI_Recv
. 发送任何数据类型的可变长度向量(例如 MPI_Float
)
问题是我不知道如何结合这两种方法。
我知道我可以:
- 首先发送 header,然后在两个单独的消息中发送第二个数据。
- 这有消息的重新排序和交织问题。我需要一种可靠、简单且可扩展的方式来关联 header 及其在
master
上的数据。对于两条消息,我看不到如何始终简单地获取 header 和主服务器上传入消息的数据。 IE。两个 worker
可以向 master
发送 hdr 和数据消息,并且它们可以交错。 (我不确定订购的保证是什么,即使在阅读了 MPI 规范之后)。
- 将 header 和数据编码为
MPI_Byte
数组,并将其作为二进制 blob 发送。
- 听起来很脏而且违反了一些保证。
我的问题是:我如何MPI-idiomatically发送一个可识别的逻辑消息,其中包含一种类型的常量大小header和一个可变大小的消息第二种类型的向量。
本程序使用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
这真的只是 proof-of-concept 代码。希望它能帮助您找到所需的解决方案。
备注
此代码不进行错误检查,不应在生产环境中使用。
我有 n workers
、1 master
(等级 0),需要通过 MPI 从 n workers
发送消息到 master
。消息格式是可变长度向量 (float *dta
) 和恒定大小 header struct { int32_t x, int32_t y } dtaHdr
.
master 只是循环传入的结果并处理它们。重要的是它能够将哪个 dtaHdr
与哪个 dta
关联起来。
我知道如何:
- 为常量
dtaHdr
创建MPI_Datatype
并通过 P2PMPI_Send
/MPI_Recv
. 发送
- 通过 P2P
MPI_Send
/MPI_Recv
. 发送任何数据类型的可变长度向量(例如
MPI_Float
)
问题是我不知道如何结合这两种方法。
我知道我可以:
- 首先发送 header,然后在两个单独的消息中发送第二个数据。
- 这有消息的重新排序和交织问题。我需要一种可靠、简单且可扩展的方式来关联 header 及其在
master
上的数据。对于两条消息,我看不到如何始终简单地获取 header 和主服务器上传入消息的数据。 IE。两个worker
可以向master
发送 hdr 和数据消息,并且它们可以交错。 (我不确定订购的保证是什么,即使在阅读了 MPI 规范之后)。
- 这有消息的重新排序和交织问题。我需要一种可靠、简单且可扩展的方式来关联 header 及其在
- 将 header 和数据编码为
MPI_Byte
数组,并将其作为二进制 blob 发送。- 听起来很脏而且违反了一些保证。
我的问题是:我如何MPI-idiomatically发送一个可识别的逻辑消息,其中包含一种类型的常量大小header和一个可变大小的消息第二种类型的向量。
本程序使用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
这真的只是 proof-of-concept 代码。希望它能帮助您找到所需的解决方案。
备注
此代码不进行错误检查,不应在生产环境中使用。