我正在尝试测试mpi请求是否已完成。但是,有一个我无法弄清楚的问题。如果我使用如下的test_all方法,那么我看到请求没有完成。
string msg;
boost::mpi::request req = world->irecv(some_rank, 0, msg);
vector<boost::mpi::request> waitingRequests;
waitingRequests.push_back(req);
if(boost::mpi::test_all(waitingRequests.begin(), waitingRequests.end()))
cout << "test_all done" << endl;
当我尝试使用此代码时,我看到请求已完成:
string msg;
boost::mpi::request req = world->irecv(some_rank, 0, msg);
if(req.test())
cout << "test done" << endl;
所以,我查看了test_all函数中的代码,并意识到由于条件“first-&gt; m_handler”(下面的代码中的第5行)它返回false。
template<typename ForwardIterator> bool test_all(ForwardIterator first, ForwardIterator last) {
std::vector<MPI_Request> requests;
for (; first != last; ++first) {
// If we have a non-trivial request, then no requests can be completed.
if (first->m_handler || first->m_requests[1] != MPI_REQUEST_NULL)
return false;
requests.push_back(first->m_requests[0]);
}
int flag = 0;
int n = requests.size();
BOOST_MPI_CHECK_RESULT(MPI_Testall,
(n, &requests[0], &flag, MPI_STATUSES_IGNORE));
return flag != 0;
}
现在,我想知道m_handler是为了什么。
答案 0 :(得分:1)
MPI不支持内部复杂的C ++对象,例如std::string
。这就是为什么Boost.MPI在以MPI消息的形式传递这些对象时序列化并相应地反序列化这些对象的原因。从语义的角度来看,irecv()
启动的非阻塞操作应该在收到数据并且std::string
对象已被适当填充后完成。处理接收消息并对其进行反序列化的附加步骤由特殊处理程序方法执行,指针存储在m_handler
变量中:
...
if (m_handler) {
// This request is a receive for a serialized type. Use the
// handler to test for completion.
return m_handler(this, ra_test);
} else ...
简单数据类型不需要这样的处理。
同样适用于isend()
在C ++对象上运行时。在这种情况下,不附加处理程序,但是类数据以两个单独的消息的形式发送,并且特别注意两个发送完成。这就是第二个布尔表达式(m_requests[1] != MPI_REQUEST_NULL
)的用途。