boost::MPI 的 irecv() 返回未初始化的状态对象
boost::mpi's irecv() returns non-initialized status objects
我正在使用irecv()
函数接收boost::mpi
消息。我有一个等待循环,调用irecv
返回的request
对象上的test()
,如果请求完成,做一些事情。然而,试图找出发件人的排名,我得到一个异常:
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消息的发送者和标签可以从请求对象中找到,就像这个答案中概述的那样。
我很高兴你解决了这个问题,但也许这将进一步解释它。
问题是成功呼叫req.test()
后再次呼叫req.test()
。在MPI -完整参考:卷1,MPI核心:
请求对象通过成功调用MPI_WAIT或MPI_TEST自动释放。
另外,从boost mpi文档中:
optional<状态> test();确定与此请求关联的通信是否已成功完成。如果是,返回描述通信的状态对象。否则,返回一个空的可选值<>,表示通信尚未完成。注意,一旦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.
修改:
- 调用
req.test()
返回boost::optional<mpi::status>
对象。 - 测试
boost::optional
对象,看req.test()
是否成功返回,如果成功,使用返回的mpi::status
。
代码:
#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
我弄清楚了:问题是我再次调用test()
,这显然使某些东西无效。它适用于
auto ret = inc.test();
if(ret) {
// use ret->source()
}
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 成员变量未保持初始化状态
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- MSVC2015初始化应保持未初始化状态的类成员
- Linux Opensuse C 编译器问题.(无法初始化部分调试器的解压缩状态)
- 是否可以在pdf文件中重新初始化图形状态
- 使无序初始化状态有序
- 如何将boost::optional设置回未初始化状态
- STL:用未构造的有状态比较器初始化容器
- boost::MPI 的 irecv() 返回未初始化的状态对象
- 在构造函数中初始化的变量未保持初始化状态 (c++)
- C++无状态类的静态初始化