测试后无法取消MPI请求

时间:2014-12-04 14:02:55

标签: c++ asynchronous boost mpi communication

我正在尝试使用boost库创建模拟,但是我遇到了进程异步通信的问题。在我们的例子中,有两个进程相互发送/接收消息(使用isend和ireceive命令)。如果我等待所有发送/接收命令完成,那么一切正常。所以,这是我的工作代码:

boost::mpi::communicator* comm;
// Initialize MPI and etc.
...

std::vector<boost::mpi::request> sendRequests;
std::vector<boost::mpi::request> receiveRequests;

for(int i=0; i< 10; i++){
    receiveRequests.push_back(comm->irecv(0, 3000, receivedMessage));
    sendRequests.push_back(comm->isend(1, 3000, sentMessage));

    boost::mpi::wait_all(receiveRequests.begin(), receiveRequests.end());
    receiveRequests.clear();
}

但是,如果花费太多时间,我想取消接收消息。因此,我尝试使用测试和取消功能测试通信是否完成。所以,我修改了我的代码,如下所示:

boost::mpi::communicator* comm;
// Initialize MPI and etc.
...

std::vector<boost::mpi::request> sendRequests;
std::vector<boost::mpi::request> receiveRequests;

for(int i=0; i< 10; i++){
    receiveRequests.push_back(comm->irecv(0, 3000, receivedMessage));
    sendRequests.push_back(comm->isend(1, 3000, sentMessage));

    vector<boost::mpi::request>::iterator it = receiveRequests.begin();
    while(it != receiveRequests.end()){
        if(!((*it).test()))
            (*it).cancel();     
        receiveRequests.erase(it);
    }
}

现在,我的程序崩溃了,我在循环的第一次迭代后得到了这个错误:

terminate called after throwing an instance of 'std::length_error'
what():  vector::_M_fill_insert
terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::mpi::exception> >'
what():  MPI_Test: Message truncated, error stack:
PMPI_Test(168)....................: MPI_Test(request=0x13bba24, flag=0x7fff081a7bd4, status=0x7fff081a7ba0) failed
MPIR_Test_impl(63)................: 
MPIDI_CH3U_Receive_data_found(129): Message from rank 0 and tag 3000 truncated; 670 bytes received but buffer size is 577

所以,我想知道如何解决这个错误。

2 个答案:

答案 0 :(得分:1)

it来自哪里?它无处可以

请注意,push_back可以重新分配,这会使任何挂起的迭代器无效。

另请注意,如果您执行删除操作,则需要有条件地增加it。典型的模式是

 it = receiveRequests.erase(it);

更新我看到您已在问题中添加了信息。应该是:

vector<boost::mpi::request>::iterator it = receiveRequests.begin();
while(it != receiveRequests.end()){
    if(!((*it).test()))
        (*it).cancel();     
    it = receiveRequests.erase(it);
}

我不确定为什么你总是擦除每个接收请求。我假设这是意图

答案 1 :(得分:0)

最后,我想通了。这只是因为测试和取消方法之间的竞争条件。由于在运行期间有数百个消息请求,因此有时会出现这种情况。在测试请求之后,程序无法取消它,因为它刚刚完成(在测试方法之后,但在取消方法之前)。这就是它不规则地发生的原因。所以,我不得不改变我想做的方式并删除取消方法。