2014-12-04 78 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