当使用序列化数据执行多个带有相同标记的isend / irecv传输时,我看到MPI_ERR_TRUNCATE
出现boost::mpi
错误。这些是不并发传输,即不涉及线程。同时还有多个未完成的转账。这是一个展示失败的简短测试程序:
#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 tags\n";
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 tags\n";
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_impl&gt;类型的未捕获异常终止:MPI_Unpack:MPI_ERR_TRUNCATE:消息截断
如果我使用本机MPI数据类型以便不调用序列化,那么事情似乎有效。我在使用OpenMPI 1.7.3的MacPorts boost 1.55上获得相同的错误,在OpenMPI 1.4.5中使用Debian提升1.49。我尝试使用相同的标签直接使用API C接口进行多次传输,这似乎有效,但当然我只能传输本机MPI数据类型。
我的问题是,在同一个代码上进行多次未完成的转移是boost::mpi
的有效操作,如果是,我的程序中存在错误或boost::mpi
中的错误?
答案 0 :(得分:4)
在当前版本的boost 1.55中,boost::mpi
不保证非超车消息。这与基础MPI API which does:
订单消息是非超车的:如果发件人发送了两封邮件 继承到同一目的地,并且两者都匹配相同的接收, 然后,如果第一个消息,则此操作无法接收第二条消息 依然悬而未决。如果一个接收器连续发布两个接收,并且 两者都匹配相同的消息,然后第二个接收操作不能 如果第一个仍然未决,请对此消息感到满意。这个 要求有助于发送与接收的匹配。它保证 如果进程是,则消息传递代码是确定性的 单线程和未使用通配符MPI_ANY_SOURCE 接收。
boost::mpi
不保证非超车的原因是序列化数据类型在两条MPI消息中传输,一条用于大小,一条用于有效载荷,第二条消息的irecv
直到检查第一条消息。
正在考虑在boost::mpi
中保证不超车的建议。可以在boost::mpi
开始here的邮件列表中找到进一步的讨论。
答案 1 :(得分:0)
问题可能在于您正在等待所有发送完成,然后等待所有收到的发送。 MPI期待您的发送和接收在时间和数量上匹配。我的意思是说,如果你的接听电话没有进展,你就无法完成所有的发送电话。
MPI通常处理发送消息的方式是,当您调用send时,一旦消息由库处理,它就会从调用中返回。这可能是消息已被复制到内部缓冲区,或者消息实际上已传输到远程进程并已被接收。无论哪种方式,消息必须去某个地方。如果您没有等待的接收缓冲区,则必须在内部缓冲该消息。最终,实现将耗尽这些缓冲区并开始做坏事(比如向用户返回错误),这可能是你在这里看到的。
解决方案是预先发布您的接收缓冲区。在您的情况下,您可以将所有isend
和irecv
调用推送到同一个向量中,让MPI处理所有内容。这将使MPI能够访问所有接收缓冲区,因此您的消息可以随处去。