boost :: mpi在具有相同标记的多个isend / irecv传输上抛出MPI_ERR_TRUNCATE

时间:2014-02-19 18:39:51

标签: c++ boost mpi boost-mpl

当使用序列化数据执行多个带有相同标记的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中的错误?

2 个答案:

答案 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时,一旦消息由库处理,它就会从调用中返回。这可能是消息已被复制到内部缓冲区,或者消息实际上已传输到远程进程并已被接收。无论哪种方式,消息必须去某个地方。如果您没有等待的接收缓冲区,则必须在内部缓冲该消息。最终,实现将耗尽这些缓冲区并开始做坏事(比如向用户返回错误),这可能是你在这里看到的。

解决方案是预先发布您的接收缓冲区。在您的情况下,您可以将所有isendirecv调用推送到同一个向量中,让MPI处理所有内容。这将使MPI能够访问所有接收缓冲区,因此您的消息可以随处去。