2014-12-04 31 views
0

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

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 

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

+0

这里没有足够的代码来重现错误,所以你所得到的只是猜测。我们可以说,根据错误消息,问题不是取消,而是测试。特别是,看起来你发布了一些接收(来自不同级别?谁知道?)带有相同标签(我猜)但长度不同(有人发送670字节长,但你期望有577字节长)。所以当测试发生时,该接收尝试失败。出于某种原因,在原始代码中,可能是由于增加的同步(谁可以说?),没有发生。 – 2014-12-04 17:15:54

+0

我试着用不同的标签发送请求,但结果是一样的。在循环的每一次迭代中,进程都会发送彼此具有不同标记的消息,但不起作用。正如你所说,它看起来错误在测试功能上。即使我不取消请求(但只是测试),我仍然会得到同样的错误。我想提供更多的代码,但我不知道我可以放什么。因为只是使用测试方法而不是等待查看错误的原因。除了这些行之外,我没有更多的代码。我的意思是他们与MPI部分无关。 – 2014-12-05 14:40:43

回答

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); 
} 

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

+0

感谢您的回答。我修正了上面的代码,并且试图按照你所说的递增迭代器。现在,它运行非确定性。有时我会在第一次迭代中得到相同的错误,有时会在第三次迭代中等等。有时我从来没有得到这个错误,程序终止如我所料。 – 2014-12-04 14:59:16

+1

你是否在其他地方增加迭代器?如果您删除了该项目,它应该**不会增加。此外,你确定矢量不能重新分配(见** [迭代器失效规则](http://stackoverflow.com/questions/6438086/iterator-invalidation-rules)**)。 – sehe 2014-12-04 15:00:24

+0

由于您已将更多信息添加到问题 – sehe 2014-12-04 15:04:01