2013-07-13 65 views
1

MPI標準3.0表示在第5.13節該MPI_Bcast使用線程(OpenMP的)在MPI

最後,在多線程實現中,一個可以在一個過程中多於一個, 同時執行,集體通信呼叫。在 這些情況下,用戶有責任確保在同一進程中通過兩個不同的集體 通信調用同時使用相同的通信器。

我寫了下面的程序不正確地執行(但編譯)和轉儲芯

void main(int argc, char *argv[]) 
{ 
int required = MPI_THREAD_MULTIPLE, provided, rank, size, threadID, threadProcRank ; 
MPI_Comm comm = MPI_COMM_WORLD ; 

MPI_Init_thread(&argc, &argv, required, &provided); 
MPI_Comm_size(comm, &size); 
MPI_Comm_rank(comm, &rank); 

int buffer1[10000] = {0} ; 
int buffer2[10000] = {0} ; 

#pragma omp parallel private(threadID,threadProcRank) shared(comm, buffer1) 
{ 
    threadID = omp_get_thread_num(); 
    MPI_Comm_rank(comm, &threadProcRank); 
    printf("\nMy thread ID is %d and I am in process ranked %d", threadID, threadProcRank); 

    if(threadID == 0) 
     MPI_Bcast(buffer1, 10000, MPI_INTEGER, 0, comm); 

    If (threadID == 1) 
     MPI_Bcast(buffer1, 10000, MPI_INTEGER, 0, comm); 
} 

    MPI_Finalize(); 
} 

我的問題是:兩個線程中的每個進程具有線程ID 0和線程ID 1柱的可以在根進程(即進程0)中作爲MPI_Send()進行廣播調用。我將它解釋爲MPI_Send()的兩個循環,其中目標是其餘進程。目標進程還會在線程ID 0和線程ID 1中發佈MPI_Bcast()。這些可以被兩個線程中的每個進程發佈爲兩個MPI_Recv()。由於MPI_Bcast()是相同的 - 在接收由進程0(根)發送的消息時,應該沒有匹配的問題。但是這個程序仍然不起作用。爲什麼?是否有可能在同一個傳播者上的不同/相同的集體上混淆了信息?而且由於MPI(mpich2)認爲這種可能性,它不允許同一個通信器上的兩個集體同時等待嗎?

回答

3

首先,您沒有檢查provided的值,其中MPI實現返回實際提供的線程支持級別。該標準允許這個水平比所要求的一個正確的MPI應用程序寧願做這樣的事情下:

MPI_Init_thread(&argc, &argv, required, &provided); 
if (provided < required) 
{ 
    printf("Error: MPI does not provide the required thread support\n"); 
    MPI_Abort(MPI_COMM_WORLD, 1); 
    exit(1); 
} 

其次,這行代碼是多餘的:

MPI_Comm_rank(comm, &threadProcRank); 

主題在MPI 不要有單獨的行列 - 只有過程有排名。有人建議在MPI 3.0中引入所謂的端點,這將允許單個進程擁有多個等級並將它們綁定到不同的線程,但它並沒有將其納入到標準的最終版本中。

第三,您在兩個集體中都使用相同的緩衝區變量。我想你的意圖是在線程0中的調用中使用buffer1,並且在線程1中的調用中使用buffer2。另外,MPI_INTEGER是與Fortran中的INTEGER相對應的數據類型。對於C int,鍵入相應的MPI數據類型爲MPI_INT

第四,MPI_BCAST作爲MPI_SEND和相應的MPI_RECV循環的解釋就是這樣一種解釋。實際上,實施方式有很大不同 - 請參閱here。例如,對於初始網絡建立延遲遠高於物理數據傳輸時間的較小消息,使用二進制和二叉樹以最小化集體的等待時間。較大的消息通常會分成許多段,然後使用管道將段從根級傳遞到所有其他段。即使在樹分佈情況下,消息仍然可以被分割。

問題在於,實際上每個集體操作都是使用具有相同標籤的消息來實現的,通常帶有負值標籤值(應用程序員不允許使用這些標籤值)。這意味着在你的情況下MPI_Bcast調用將使用相同的標籤來傳輸他們的消息,並且由於隊伍將是相同的,並且溝通者是相同的,所以消息將全部混合起來。因此只有在不同的傳播者之間進行併發集體的要求。

你的程序崩潰有兩個原因。原因之一是MPI庫不提供MPI_THREAD_MULTIPLE。第二個原因是如果消息被分成兩個大小不一的塊,例如一個較大的第一部分和一個較小的第二部分。兩個集體調用之間的干擾可能導致第二個線程在等待第二個較小的塊時接收指向第一個線程的較大的第一個塊。結果將是消息截斷,並且中止MPI錯誤處理程序將被調用。這通常不會導致段錯誤和核心轉儲,所以我會假設您的MPICH2不會被編譯爲線程安全的。

這不是MPICH2特有的。開放MPI和其他實現也容易受到相同的限制。

+0

謝謝您抽出時間詳細回答。 –

+0

第一:我檢查了提供的值,它是MPI_THREAD_MULTIPLE。第二:我故意看到哪個線程在哪個進程中THIRD:再次故意,因爲我想MPI_Bcast()看起來相同。第四:你對二進制和二叉樹的實現是正確的,但我期望2進程只有他們會直接去做一個簡單的SEND和RECV。您對碎片做了一個很好的說明 - 我已經將它添加到了我的想法中:) FIFTH:某處MPI_Bcast()使用標記,因爲我可以通過MPI_ANY_TAG發佈MPI_Back()和MPI_Recv()。非常感謝! –