2016-01-26 71 views
0

我有以下的C/C++與微軟MPI死鎖中的Microsft MPI MPI_Isend

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 
int main (int argc, char *argv[]) 
{ 
    int err, numtasks, taskid; 
    int out=0,val; 
    MPI_Status status; 
    MPI_Request req; 

    err=MPI_Init(&argc, &argv); 
    err=MPI_Comm_size(MPI_COMM_WORLD, &numtasks); 
    err=MPI_Comm_rank(MPI_COMM_WORLD, &taskid); 


    int receiver=(taskid+1)% numtasks; 
    int sender= (taskid-1+numtasks)% numtasks; 
    printf("sender %d, receiver %d, rank %d\n",sender,receiver, taskid); 

    val=50; 
    MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req); 
    MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req); 
    printf ("Rank: %d , Value: %d\n", taskid, out); 
    err=MPI_Finalize(); 
    return 0; 
} 

應用程序代碼放在僵局,如果有超過2個進程啓動。 使用2個進程,應用程序可以正常工作,但不會寫入「out」。 此代碼適用於Linux mpi發行版,該問題似乎只適用於Microsoft版本。任何幫助?

回答

3

首先,每個MPI進程正在執行兩個通信:單個發送和單個接收。所以你需要存儲兩個請求(MPI_Request req[2])和兩個狀態檢查(MPI_Status status[2])。其次,在調用非阻塞send/recvs以確保它們正確完成之後,您需要等待。

MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req[0]); 
MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req[1]); 

// While the communication is happening, here you can overlap computation 
// on data that is NOT being currently communicated, with the communication of val/out 

MPI_Waitall(2, req, status); 

// Now both the send and receive have been finished for this process, 
// and we can access out, assured that it is valid 

printf ("Rank: %d , Value: %d\n", taskid, out); 

至於爲什麼這個工作的一個Linux發行版,而不是微軟一個...我只能假設,在引擎罩Linux實現有效地實現無阻塞通信爲阻止通信。也就是說,他們是「作弊」並在你完成之前完成你的溝通。這使得它們變得更容易,因爲它們不必跟蹤關於通信的儘可能多的信息,但它也破壞了重疊計算和通信的能力。你不應該依靠這個工作。

+0

爲什麼我需要使用非阻塞呼叫進行等待?我應該有不一致的數據,而不是死鎖,對吧?爲什麼在Linux發行版中我不需要「等待」電話? – Discipulos

+0

@Discipulos你是對的。非阻塞通信允許您在整個流程中存在不一致的數據。但是,在您可以訪問數據之前,您必須確認通信完成。因此需要等待。我已經編輯了這篇文章,以更清楚地展示這可以讓你做什麼。 – NoseKnowsAll

+0

也許Microsoft實施了非純粹的非阻塞通信,這解釋了我注意到的行爲。 謝謝! – Discipulos