2011-10-23 26 views
58

我試圖使用MPI_Bcast從根節點向所有其他節點廣播消息。然而,每當我運行這個程序時,它總是會在開始時掛起。有人知道它有什麼問題嗎?使用MPI_Bcast進行MPI通信

#include <mpi.h> 
#include <stdio.h> 

int main(int argc, char** argv) { 
     int rank; 
     int buf; 
     MPI_Status status; 
     MPI_Init(&argc, &argv); 
     MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

     if(rank == 0) { 
       buf = 777; 
       MPI_Bcast(&buf, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     } 
     else { 
       MPI_Recv(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); 
       printf("rank %d receiving received %d\n", rank, buf); 
     } 

     MPI_Finalize(); 
     return 0; 
} 

回答

107

這是MPI新手的常見混淆之處。您不使用MPI_Recv()接收廣播發送的數據;你使用MPI_Bcast()

例如,你想要的是這樣的:

#include <mpi.h> 
#include <stdio.h> 

int main(int argc, char** argv) { 
     int rank; 
     int buf; 
     const int root=0; 

     MPI_Init(&argc, &argv); 
     MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

     if(rank == root) { 
      buf = 777; 
     } 

     printf("[%d]: Before Bcast, buf is %d\n", rank, buf); 

     /* everyone calls bcast, data is taken from root and ends up in everyone's buf */ 
     MPI_Bcast(&buf, 1, MPI_INT, root, MPI_COMM_WORLD); 

     printf("[%d]: After Bcast, buf is %d\n", rank, buf); 

     MPI_Finalize(); 
     return 0; 
} 

對於MPI集體通信,大家具有能參與;每個人都必須打電話給Bcast或Allreduce,或者你有什麼。 (這就是爲什麼Bcast例程有一個指定「root」的參數,或者是誰在進行發送;如果只有發送者調用了bcast,你就不需要這個了。)每個人都會調用廣播,包括接收者;收件人不只是發佈一個接收。

原因是集體操作可能涉及到每個人的溝通,所以你說出你想要發生的事情(每個人都得到一個進程的數據)而不是它發生了什麼它發生了什麼(例如,根處理器循環超過所有其他級別並進行發送),因此存在優化通信模式的範圍(例如,針對P進程採取步驟log(P)而非P步驟的基於樹的分級通信)。

+0

感謝你的解釋。然而,我仍然對如何讓每個節點使用MPI_Recv接收消息感到困惑。我嘗試在if(rank!= 0)塊中包裝MPI_Recv調用,但沒有一個,但我的程序仍然不打印任何內容。你知道如何在每個節點上接收消息嗎? – David

+1

你沒有。 MPI_Bcast不像發送;這是一個集體操作,每個人都參與發送者和接收者,並且在通話結束時,接收者具有發送者的價值。如果rank == root(這裏是0)和(類似的)a是相同的函數調用,則發送(類似)發送。我已經更新了上面的代碼,所以你可以看到每個人都會得到相同的結果。 –

+5

@David:如果你認爲'MPI_Bcast'是'參與廣播事件'的意思,那麼它可能更有意義。 –

1

MPI_Bcast是一個集體操作,它必須被所有進程調用才能完成。

使用MPI_Bcast時無需致電MPI_Recv。還有另一篇文章可能會對你有所幫助,click here