boost::mpi在具有相同标记的多个isend/irecv传输上抛出mpi_ERR_TRUNCATE
boost::mpi throws MPI_ERR_TRUNCATE on multiple isend/irecv transfers with same tag
当使用序列化数据对同一标记执行多个isend/irecv传输时,我看到boost::mpi
出现MPI_ERR_TRUNCATE
错误。这些是而不是并发传输,即不涉及线程。同时只有一笔以上的转账未结清。下面是一个显示失败的简短测试程序:
#include <iostream>
#include <string>
#include <vector>
#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
static const size_t N = 2;
int main() {
boost::mpi::environment env;
boost::mpi::communicator world;
#if 1
// Serialized types fail.
typedef std::string DataType;
#define SEND_VALUE "how now brown cow"
#else
// Native MPI types succeed.
typedef int DataType;
#define SEND_VALUE 42
#endif
DataType out(SEND_VALUE);
std::vector<DataType> in(N);
std::vector<boost::mpi::request> sends;
std::vector<boost::mpi::request> recvs;
sends.reserve(N);
recvs.reserve(N);
std::cout << "Multiple transfers with different tagsn";
sends.clear();
recvs.clear();
for (size_t i = 0; i < N; ++i) {
sends.push_back(world.isend(0, i, out));
recvs.push_back(world.irecv(0, i, in[i]));
}
boost::mpi::wait_all(sends.begin(), sends.end());
boost::mpi::wait_all(recvs.begin(), recvs.end());
std::cout << "Multiple transfers with same tagsn";
sends.clear();
recvs.clear();
for (size_t i = 0; i < N; ++i) {
sends.push_back(world.isend(0, 0, out));
recvs.push_back(world.irecv(0, 0, in[i]));
}
boost::mpi::wait_all(sends.begin(), sends.end());
boost::mpi::wait_all(recvs.begin(), recvs.end());
return 0;
}
在这个程序中,我首先在不同的标签上进行2次传输,效果很好。然后我尝试在同一个标签上进行2次传输,但失败的原因是:
libc++abi.dylib:终止于类型为boost::exception_detail::clone_empl>的未捕获异常:MPI_Unpack:MPI_ERR_TRUNCATE:消息截断
如果我使用本机MPI数据类型,这样就不会调用序列化,那么一切似乎都正常。我在使用OpenMPI 1.7.3的MacPorts boost 1.55和使用OpenMPI 1.4.5的Debian boost 1.49上得到了相同的错误。我尝试使用API C接口直接对同一个标记进行多次传输,这似乎有效,当然我只能传输本机MPI数据类型。
我的问题是,在同一个标签上有多个未完成的传输是否是boost::mpi
的有效操作,如果是,我的程序中是否存在错误,或者boost::mpi
中是否存在缺陷?
在当前版本的boost 1.55中,boost::mpi
不保证不超过消息。这与底层的MPI API形成了鲜明对比,后者确实做到了:
订单消息不可超越:如果发件人在连续到相同目的地并且两者都匹配相同的接收,如果第一条消息是,则此操作无法接收第二条消息仍处于挂起状态。如果接收方连续发布两个接收方,并且两者都匹配相同的消息,则第二个接收操作无法如果第一条消息仍处于挂起状态,请对此消息感到满意。这该要求有助于匹配发送和接收。它保证如果进程单线程且通配符MPI_ANY_SOURCE未在中使用接收。
boost::mpi
不能保证不超越的原因是,序列化的数据类型在两个MPI消息中传输,一个用于大小,一个用作有效载荷,而第二个消息的irecv
在检查第一个消息之前无法发布。
正在考虑一项保证boost::mpi
不超车的建议。从这里开始,可以在boost::mpi
邮件列表中找到进一步的讨论。
问题可能是您正在等待所有发送完成,然后等待所有接收。MPI希望您的发送和接收在时间和数量上匹配。我这么说的意思是,如果你的接听电话没有进展,你就无法完成所有的发送电话。
MPI通常处理发送消息的方式是,当您调用send时,一旦库处理了消息,它就会从调用中返回。这可能是消息已复制到内部缓冲区,或者消息实际上已传输到远程进程并已被接收。无论哪种方式,信息都必须指向某个地方。如果您没有等待接收缓冲区,则必须在内部缓冲消息。最终,实现将耗尽这些缓冲区,并开始做坏事(比如向用户返回错误),您可能会在这里看到这种情况。
解决方案是预先发布接收缓冲区。在您的情况下,您可以将所有isend
和irecv
调用推送到同一个向量中,并让MPI处理所有内容。这将允许MPI访问所有的接收缓冲区,这样您的消息就有了用武之地。
- 用MacOS Mojave编译C++:致命错误:mpi.h:没有这样的文件或目录
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- Angelscript从C++传输数组
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- MPI突然停止了对多个核心的操作
- 从服务器传输到客户端的消息不会出现
- 设置 Visual Studio for MPI: 找不到标识符错误
- USB传输的LibUSB C++格式不同
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何使用 MPI 的远程内存访问 (RMA) 功能并行化数据聚合?
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- 将相机数据从服务器实时流式传输到客户端
- 重载 MPI 中的运算符 ()
- 加密在 Windows、C++ 和 Java 中传输中的数据
- 分段错误:C++中的结构序列化和 MPI 数据传输
- boost::mpi在具有相同标记的多个isend/irecv传输上抛出mpi_ERR_TRUNCATE
- 未知子类的 MPI 传输与 boost::mpi::p acked_oarchive 和 packed_iarchive
- 如何使用mpi将文件从一个进程传输到另一个进程
- 如何使用MPI在多个独立启动的程序之间传输数据
- 如何在mpi中传输数据