2012-05-18 24 views
6

一個看似愚蠢的問題,但我似乎無法以某種方式找到確定的答案。我是否需要爲MPI :: Isend提供相應的MPI :: Irecv?

基本問題是我需要爲MPI :: Isend具有相應的MPI :: Irecv嗎?

也就是說,即使消息發送是非阻塞的,只要我在重新使用發送緩衝區之前等待發送完成,我是否需要使用非阻塞接收等待來接收發送的緩衝區?

我的觀點是,我想在發送消息時使用非阻塞發送來「做其他事情」,但接收器進程將立即使用緩衝區,所以我希望它們阻塞,直到真正接收到緩衝區。

看起來我應該能夠接收MPI :: Recv消息,即使它們是用MPI :: Isend發送的但我想知道如果我錯過了什麼嗎?

簡單的僞代碼有點

if(rank == 0){ 
    int r; 
    for (int i = 0; i < n; i++){ 

    // DO SOME STUFF HERE... 

    request.Wait(status); 
    request2.Wait(status); 
    request3.Wait(status); 

    r = i; 
    memcpy(key, fromKey(i), ...); 
    memcpy(trace, fromTrace(i), ...); 

    request = MPI::COMM_WORLD.Isend(&r, 1, MPI::INT, node, tag); 
    request2 = MPI::COMM_WORLD.Isend(key, 10, MPI::INT, node, tag); 
    request3 = MPI::COMM_WORLD.Isend(trace, nBytesTotal, MPI::BYTE, node, tag); 

    // DO SOME MORE STUFF HERE. 

    } 
    r = -1; 
    request = MPI::COMM_WORLD.Isend(&r, 1, MPI::INT, node, tag); 

    // Carry on ... 

    } else { 

    int r = -1; 
    MPI::COMM_WORLD.Recv(&r, 1, MPI::INT, 0, tag, status); 
    while(r >= 0){ 

    MPI::COMM_WORLD.Recv(&key, 10, MPI::INT, 0, tag, status); 
    memcpy(saveKey, key, ...); 

    MPI::COMM_WORLD.Recv(&trace, nBytesTotal, MPI::BYTE, 0, tag, status); 
    memcpy(saveTrace, trace, ...); 

    MPI::COMM_WORLD.Recv(&r, 1, MPI::INT, 0, tag, status); 
    } 
+0

在這裏的答案可能會讓你感興趣:http://stackoverflow.com/questions/9408704/mpi-send-and-receive-questions –

回答

15

不,您可以在通信的兩端自由混合阻塞和非阻塞MPI操作。阻塞與MPI調用何時將控制權返回給您的代碼而不是正在傳輸的消息的內容有關。

每個MPI消息都帶有一個「信封」,包含它的源,目的地,標籤和通信器。要成功收到郵件,您的接收操作應該只有匹配其信封。信封決不會指定郵件的確切發送方式 - 是通過阻止,是通過非阻止操作,是同步發送(MPI_Ssend)還是緩衝郵件(MPI_Bsend)。唯一的例外是通過MPI_Rsend()MPI_Irsend()啓動的所謂「就緒模式」發送,它要求匹配的接收操作已經發布或者消息不會被髮送。

這就是爲什麼在整個MPI標準中使用術語「匹配接收操作」而不是像「相應的接收函數」那樣的原因。

+0

所以答案是:「不需要,MPI :: Isend不需要相應的MPI :: Irecv」。和我想的一樣。否則,我會感到驚訝。感謝細節。 – user1074069

+0

編輯使我的觀點更清晰:) –

0

是的,這是好的。沒有要求send/recv「種類」(或任何你想要稱之爲)匹配。

+0

這就是我的想法。否則,我會感到驚訝。我想我真的擔心在這種情況下是否有任何實現可能會做出奇怪的事情。 – user1074069

0

這不管你用什麼send/recv;但實施很重要。您必須瞭解代碼中的阻止點。例如在使用阻擋你一定要小心通信有關發送,並在此代碼

if(rank==0) 
{ 
MPI_Send(x to process 1) 
MPI_Recv(y from process 1) 
} 
if(rank==1) 
{ 
MPI_Send(y to process 0); 
MPI_Recv(x from process 0); 
} 

什麼在這種情況下發生的接收例如 看電話? 進程0將x發送到進程1並阻塞,直到進程1接收到x,進程0將y發送到進程0並阻塞,直到進程0接收到y,但進程0被阻止,因此進程1阻止無限,直到您終止2進程