2013-05-17 237 views
0

我想從每個進程發送一些數據給它的鄰居(按等級)。爲此,我嘗試使用非阻塞的發送和接收呼叫MPI_Isend/MPI_Irecv和相應的呼叫MPI_Waitall以確保在使用數據之前發生了傳輸。「死鎖」與MPI_Waitall

下面是我想要做的

#include <mpi.h> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    MPI_Init(&argc,&argv); 
    int rank,comm_size; 

    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
    MPI_Comm_size(MPI_COMM_WORLD,&comm_size); 

    MPI_Request reqs[4]; 

    int sbuff1[10]; 
    int sbuff2[10]; 
    int rbuff1[10]; 
    int rbuff2[10]; 

    int count = 0; 

    if(rank>0) 
    { 
     MPI_Irecv(rbuff1,10,MPI_INT,rank-1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff1,10,MPI_INT,rank-1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    if(rank<comm_size-1) 
    { 
     MPI_Irecv(rbuff2,10,MPI_INT,rank+1,2,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff2,10,MPI_INT,rank+1,3,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    MPI_Waitall(count,reqs,MPI_STATUS_IGNORE); 

    if(rank==0) 
      cout << "Successfully exchanged data." << endl; 

    MPI_Finalize(); 

    return 0; 
} 

一個小例子,不幸的是這代碼永遠不會使它通過在最後打印出來的消息。

我的問題是:數據是否正確發送,但我打電話給MPI_Waitall是某種錯誤?如果是的話,我需要改變什麼才能使這個簡單的代碼運行,如果不是,還有什麼是錯誤的?

回答

1

您設置的send/recv標籤永遠不會匹配。

這一點修復

#include <mpi.h> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    MPI_Init(&argc,&argv); 
    int rank,comm_size; 

    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
    MPI_Comm_size(MPI_COMM_WORLD,&comm_size); 

    MPI_Request reqs[4]; 

    int sbuff1[10]; 
    int sbuff2[10]; 
    int rbuff1[10]; 
    int rbuff2[10]; 

    int count = 0; 

    if(rank>0) 
    { 

     MPI_Irecv(rbuff1,10,MPI_INT,rank-1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff1,10,MPI_INT,rank-1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    if(rank<comm_size-1) 
    { 
     /// changed tag 2 -> 1 
     // MPI_Irecv(rbuff2,10,MPI_INT,rank+1,2,MPI_COMM_WORLD,&reqs[count]); 
     MPI_Irecv(rbuff2,10,MPI_INT,rank+1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 

     /// changed tag 3 -> 0 
     // MPI_Isend(sbuff2,10,MPI_INT,rank+1,3,MPI_COMM_WORLD,&reqs[count]); 
     MPI_Isend(sbuff2,10,MPI_INT,rank+1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    MPI_Waitall(count,reqs,MPI_STATUS_IGNORE); 

    if(rank==0) 
      cout << "Successfully exchanged data." << endl; 

    MPI_Finalize(); 

    return 0; 
} 

使得它的工作

$> mpirun -n 5 ./testling 
Successfully exchanged data. 

跑x86_84的Linux與MPICH2 V1.5(九頭蛇)

+0

衛生署!我確實嘗試了不同的標籤,但我想我沒有選擇正確的組合。我從來沒有真正理解標籤的用途。我已經編寫了程序,之後在每次MPI調用後任意遞增標籤,並且這樣工作正常嗎? – Dan

+0

如果對話框是同步的,並且正確地遞增標籤,那麼沒有預期的危害。順便說一句 - 我不想打擾太多,但我認爲你會用((rank + 1)%comm_size)分支邏輯做得更好。 – Solkar

+0

我不需要在第一個和最後一個流程之間進行轉換,因此它可以,但謝謝。 – Dan