MPI_Pack:无效缓冲区指针
MPI_Pack: Invalid buffer pointer
所以,这就是我的任务。我应该在主进程中读取K - 1个三元组(K -是进程数)。该三元组由两个整型数和一个双精度数组成。我必须使用MPI_Pack和一个集体操作来将这个三元组发送给其他进程。但是当使用MPI_Pack时,我得到一个错误:无效缓冲区指针。下面是我的代码:
int flag;
MPI_Initialized(&flag);
if (flag == 0)
return;
int rank, size;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int* intbuf = new int[2];
double doublebuf;
byte* rbuf = new byte[(size - 1)*(2 * sizeof(int)+sizeof(double))];
if (rank == 0) {
int pos = 0;
for (int i = 0; i < size - 1; ++i){
pt >> intbuf[1] >> intbuf[2] >> doublebuf; //pt is from the special library and it's okay
MPI_Pack(intbuf, 2, MPI_INT, rbuf, sizeof(int)* 2, &pos, MPI_COMM_WORLD);
MPI_Pack(&doublebuf, 1, MPI_DOUBLE, rbuf, sizeof(double), &pos, MPI_COMM_WORLD);
}
}
MPI_Bcast(rbuf, sizeof(rbuf), MPI_PACKED, 0, MPI_COMM_WORLD);
if (rank != 0){
int pos = 0;
for (int i = 0; i < size - 1; ++i){
MPI_Unpack(rbuf, sizeof(int)* 2, &pos, intbuf, 2, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(rbuf, sizeof(double), &pos, &doublebuf, 1, MPI_DOUBLE, MPI_COMM_WORLD);
pt << intbuf[1] << intbuf[2] << doublebuf;
}
}
我做错了什么?
主要问题来自这一行:
MPI_Bcast(rbuf, sizeof(rbuf), MPI_PACKED, 0, MPI_COMM_WORLD);
更具体地说,它来自sizeof(rdbuf)
,应该被pos
取代。事实上,sizeof(rdbuf)
是一个sizeof(byte*)
,这取决于你的操作系统可能是4或8,但这将与你试图传输的数据大小无关……如果这个问题解决了,你的代码可能会"工作"。
然而,这仍然有很多问题:
- 你用某种任意大小分配你的打包缓冲区,这几乎没有意义。通常,要知道打包一些数据需要多少内存,应该使用
MPI_Pack_size()
。 - 你为什么要使用
MPI_Pack()
呢?这个函数是PVM遗留下来的。并行虚拟机),这是一个消息传递库预先存在的MPI。此函数的目的是简化从PVM到MPI的转换,但肯定不能用于从头开发。
为了解决你的问题,我建议你调用2个不同的MPI_Bcast()
,一个是你的2个整数,一个是你的双精度。这是非常简单直接的。
另一种可能性(如果可伸缩性很重要的话更好)是创建一个包含int型和double型的结构体,并使用MPI_Type_create_struct()
创建一个匹配的MPI结构化类型。
所以我刚刚修正了我的错误。错误是在打包数据时发生的:MPI_Pack的第5个协议并不意味着你打包了多少数据,它意味着你的缓冲区的大小(在我的情况下,缓冲区是rbuf), MPI_Unpack的第二个参数具有相同的语义。这是固定的代码。它的工作原理。
int* intbuf = new int[2];
double doublebuf;
int N = (size - 1)*(2 * sizeof(int)+sizeof(double));
byte* rbuf = new byte[N];
int pos = 0;
if (rank == 0) {
for (int i = 0; i < size - 1; ++i){
pt >> intbuf[0] >> intbuf[1] >> doublebuf;
MPI_Pack(intbuf, 2, MPI_INT, rbuf, N, &pos, MPI_COMM_WORLD);
MPI_Pack(&doublebuf, 1, MPI_DOUBLE, rbuf, N, &pos, MPI_COMM_WORLD);
}
}
MPI_Bcast(rbuf, N, MPI_PACKED, 0, MPI_COMM_WORLD);
if (rank != 0){
int pos = 0;
for (int i = 0; i < size - 1; ++i){
int* intbuf_out = new int[2];
double doublebuf_out;
MPI_Unpack(rbuf, N, &pos, intbuf_out, 2, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(rbuf, N, &pos, &doublebuf_out, 1, MPI_DOUBLE, MPI_COMM_WORLD);
pt << intbuf_out[0] << intbuf_out[1] << doublebuf_out;
delete(intbuf_out);
}
}
相关文章:
- 将字符缓冲区强制转换为函数指针
- 将指针作为缓冲区传递到第一个字符串元素
- 将constexpr字节数组与缓冲区的一部分(指向数据的指针)进行比较
- char p[0]表示自动分配的缓冲区还是安全指针
- 指针符号在参数规范中表示什么,例如:(char16 *缓冲区,int32 大小)?C++
- OpenGL:使用指向静态数据的指针数组传递缓冲区数据
- 重置/包装 C/C++ 中的变量(环缓冲区指针)
- 将 char* 推送到矢量时出现问题,但在每次迭代后,它会将指向相同值缓冲区的指针添加到矢量中
- 返回指向矢量数据的指针,而不复制缓冲区和内存泄漏
- memcpy指向炭缓冲区的指针
- 来自 2 个指针的组合缓冲区,无需复制
- 来自指针向量的OpenGL阵列缓冲区
- C++:使用std::ifstream读取二进制文件后删除缓冲区/指针时发生访问冲突
- 如何将一个缓冲区指针的内容复制到另一个缓冲区指针
- 正在将缓冲区/指针设置为null
- 将额外的字节填充到要通过网络发送的flatbuffer的缓冲区指针
- 从缓冲区指针计算堆栈中的返回地址
- MPI_scatter:缓冲区指针无效
- MPI_Pack:无效缓冲区指针
- GetIndices()会在CreateIndexBuffer()和SetIndices()之后返回相同的缓冲区指针吗?