boost :: mpi的irecv()返回非初始化的状态对象

时间:2016-09-17 12:41:58

标签: c++ boost mpi

我正在使用boost::mpi功能收到irecv()条消息。我有一个等待循环,在test()返回的request对象上调用irecv,如果请求完成,则执行某些操作。但是,试图找出发件人的排名,我得到一个例外:

boost::optional<T>::reference_type boost::optional<T>::get() [with T = boost::mpi::status; boost::optional<T>::reference_type = boost::mpi::status&]: Assertion `this->is_initialized()' failed.

这是我的代码段:

mpi::request inc = world.irecv(mpi::any_source, MpiHandler::MPI_RESULT, pxl_results);
do {
    if(inc.test()) {
        // fails here, as the optional<status> returned by inc.test() is not initialized.
        world.send(inc.test().get().source(), MpiHandler::MPI_WORK, package);
        ...
    }
} while(...);

如果我检查inc.test().is_initialized(),我发现optional<status>确实未初始化。这里发生了什么,为什么我找不到关于我的MPI发件人的任何信息?可能mpi::any_source可能与irecv无关吗?

只需添加:通常,可以从请求对象中找到MPI邮件的发件人和标记,如this answer中所述。

2 个答案:

答案 0 :(得分:1)

我很高兴你能解决这个问题,但也许这会进一步解释它。

问题是在成功调用req.test()后再次呼叫req.test()。在 MPI - 完整参考:第1卷,MPI核心

  

成功调用MPI_WAIT或MPI_TEST会自动释放请求对象。

另外,来自boost mpi文档:

  

任选的LT;状态&gt;测试();     确定与此请求关联的通信是否已成功完成。如果是,则返回描述通信的状态对象。否则,返回一个空的可选&lt;&gt;表示通讯尚未完成。 请注意,一旦test()返回状态对象,请求就完成了,不应该调用wait()。

因此,在if(req.test())成功返回boost::optional<mpi::status>之后,对req.test()的后续调用可能会返回空optional<>,从而导致您的例外。

为了看到这一点,我们首先从链接答案中的Jonathan Dursi的hello world示例中创建一个示例:

#include <boost/mpi.hpp>
#include <iostream>
#include <string>
#include <boost/serialization/string.hpp>
namespace mpi = boost::mpi;

int main()
{
  mpi::environment env;
  mpi::communicator world;

  if (world.rank() == 0) {
    std::string msg, out_msg = "Hello from rank 0.";
    world.send(1, 17, out_msg);
  } else {
    mpi::request req;
    std::string rmsg;

    req = world.irecv(mpi::any_source, mpi::any_tag, rmsg);
    do {
      if(req.test()) {
        // fails here, as the optional<status> returned by inc.test() is not initialized.
        std::cout << "From   " << req.test().get().source() << std::endl;
        std::cout << "Got " << rmsg << std::endl;
        break;
      }
    } while(1);
  }

  return 0;
}

构建并运行此操作会导致预期的异常:

[ronin:~/Documents/CPP] aichao% mpirun --hostfile hostfile -np 2 ./test_mpi_request
From   Assertion failed: (this->is_initialized()), function get, file /Users/Shared/Tools/boost_1_53_0/boost/optional/optional.hpp, line 631.

解决此问题:

  1. 致电req.test()以返回boost::optional<mpi::status>个对象。
  2. 测试boost::optional对象以查看req.test()是否成功返回,如果成功,请使用返回的mpi::status
  3. 代码:

    #include <boost/mpi.hpp>
    #include <iostream>
    #include <string>
    #include <boost/serialization/string.hpp>
    namespace mpi = boost::mpi;
    
    int main()
    {
      mpi::environment env;
      mpi::communicator world;
    
      if (world.rank() == 0) {
        std::string msg, out_msg = "Hello from rank 0.";
        world.send(1, 17, out_msg);
      } else {
        mpi::request req;
        std::string rmsg;
    
        req = world.irecv(mpi::any_source, mpi::any_tag, rmsg);
        do {
          boost::optional<mpi::status> stat = req.test();
          if (stat) {
            std::cout << "From   " << stat->source() << std::endl;
            std::cout << "Got " << rmsg << std::endl;
            std::cout << "Tagged " << stat->tag() << std::endl;
            break;
          }
        } while(1);
      }
    
      return 0;
    }
    

    现在,我们取得了成功:

    [ronin:~/Documents/CPP] aichao% mpirun --hostfile hostfile -np 2 ./test_mpi_request
    From   0
    Got Hello from rank 0.
    Tagged 17
    

答案 1 :(得分:0)

我明白了:问题是我再次打电话给test(),这显然使某些事情无效。它适用于

auto ret = inc.test();
if(ret) {
    // use ret->source()
}