c - 在一条消息中发送带有常量标头的可变长度向量
问题描述
我有 n workers
, 1 master
(排名 0),需要通过 MPI 从 n 发送消息workers
到master
. 消息格式是可变长度向量 ( float *dta
) 和恒定大小的标头struct { int32_t x, int32_t y } dtaHdr
。
master 只是遍历传入的结果并处理它们。能够将哪个dtaHdr
与哪个相关联是很重要的dta
。
我知道如何:
MPI_Datatype
为常量大小创建dtaHdr
并通过 P2PMPI_Send
/发送MPI_Recv
。MPI_Float
通过 P2PMPI_Send
/发送任何数据类型(例如 )的可变长度向量MPI_Recv
。
问题是我不知道如何结合这两种方法。
我知道我可以:
- 在两个单独的消息中先发送标头,然后再发送数据。
- 这有消息的重新排序和交错的问题。我需要一种可靠、简单且可扩展的方式来将标头及其数据关联到
master
. 有两条消息,我看不到如何始终简单地获取主控上传入消息的标头和数据。即两个worker
s 可以发送 hdr & 数据消息到master
& 他们可以成为交错。(即使在阅读 MPI 规范之后,我也不确定订购的保证是什么 TBH)。
- 这有消息的重新排序和交错的问题。我需要一种可靠、简单且可扩展的方式来将标头及其数据关联到
- 将标头和数据都编码到一个
MPI_Byte
数组中,并将其本质上作为二进制 blob 发送。- 听起来真的很脏并且违反了一些保证。
我的问题是:我如何以 MPI 惯用的方式发送一个可识别的逻辑消息,其中包含一种类型的恒定大小的标头和第二种类型的可变大小的向量。
解决方案
该程序使用MPI_Pack
andMPI_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
这实际上只是概念验证代码。希望它能帮助您找到您正在寻找的解决方案。
笔记
此代码不进行错误检查,不应在生产环境中使用。
推荐阅读
- uicollectionviewcell - iOS14中的自定尺寸UICollectionViewCell
- java - Spring Boot + Jpa:如何使这种查找方法起作用?
- node.js - 尝试将值推送到不存在的字段,但不会使用 Mongoose 推送
- r - 用散点图显示一些 x 变量的箱线图
- javascript - 即使我尝试保存,使用反应输入字段也会说合成,并且设置 value 而不是 defaultValue 正在呈现 [Object, object]
- javascript - 在 TypeScript 中克隆对象数组
- python - 计算一列中有多少字符出现在另一列(熊猫)
- html - 在 Github 上的 readme.md 中发布 R 表
- html - 为什么数据表的搜索选项不显示?
- java - Hazelcast Nearcache 服务器 - 客户端 Spring Boot