2011-04-07 62 views
2

我在MPI中使用非阻塞通信在進程之間發送各種消息。但是,我似乎陷入了僵局。我已經使用PADB(see here)看消息隊列,並已得到了以下的輸出:MPI_Isend和MPI_Irecv似乎造成了死鎖

1:msg12: Operation 1 (pending_receive) status 0 (pending) 
1:msg12: Rank local 4 global 4 
1:msg12: Size desired 4 
1:msg12: tag_wild 0 
1:msg12: Tag desired 16 
1:msg12: system_buffer 0 
1:msg12: Buffer 0xcaad32c 
1:msg12: 'Receive: 0xcac3c80' 
1:msg12: 'Data: 4 * MPI_FLOAT' 
-- 
1:msg32: Operation 0 (pending_send) status 2 (complete) 
1:msg32: Rank local 4 global 4 
1:msg32: Actual local 4 global 4 
1:msg32: Size desired 4 actual 4 
1:msg32: tag_wild 0 
1:msg32: Tag desired 16 actual 16 
1:msg32: system_buffer 0 
1:msg32: Buffer 0xcaad32c 
1:msg32: 'Send: 0xcab7c00' 
1:msg32: 'Data transfer completed' 
-- 
2:msg5: Operation 1 (pending_receive) status 0 (pending) 
2:msg5: Rank local 1 global 1 
2:msg5: Size desired 4 
2:msg5: tag_wild 0 
2:msg5: Tag desired 16 
2:msg5: system_buffer 0 
2:msg5: Buffer 0xabbc348 
2:msg5: 'Receive: 0xabd1780' 
2:msg5: 'Data: 4 * MPI_FLOAT' 
-- 
2:msg25: Operation 0 (pending_send) status 2 (complete) 
2:msg25: Rank local 1 global 1 
2:msg25: Actual local 1 global 1 
2:msg25: Size desired 4 actual 4 
2:msg25: tag_wild 0 
2:msg25: Tag desired 16 actual 16 
2:msg25: system_buffer 0 
2:msg25: Buffer 0xabbc348 
2:msg25: 'Send: 0xabc5700' 
2:msg25: 'Data transfer completed' 

這似乎已經顯示發送已經完成,但所有收到的待決(以上只是一個小部分日誌的標籤值爲16)。但是,這怎麼發生呢?當MPI中所有發送和接收都必須匹配時,必定發送不能完成的相關接收完成。至少這是我的想法...

任何人都可以提供任何見解?

我可以提供我用來做這件事的代碼,但是肯定Isend和Irecv應該工作,不管它們被調用的順序是什麼,假設MPI_Waitall在最後被調用。

更新:代碼可在this gist

更新:我已經做了多處修改代碼,但它仍然是不太正常工作。新代碼位於the same gist,我得到的輸出是this gist。我有一些疑問/問題與此代碼:

  1. 爲什麼從最終循環的輸出(打印所有陣列)與輸出的其餘部分穿插時,我有一個MPI_Barrier()之前,確保在打印之前完成所有工作?

  2. 從等級0發送到等級0是可能的/明智的 - 將工作好嗎? (當然,假設發佈了正確的匹配接收)。

  3. 我在輸出中得到了很多非常奇怪的長數字,我認爲這是一些內存覆蓋問題或變量大小問題。有趣的是,這一定是由MPI通信產生的,因爲我初始化new_array的值爲9999.99,通信顯然會導致它被改變爲這些奇怪的值。任何想法爲什麼?

總體看來,一些換位的發生(矩陣的位似乎被調換......),但絕對不是全部 - 那就是都上來了那些擔心我這些陌生號碼最多!

+2

一個發送可以在匹配接收完成之前完成,並且非常封閉地發送和接收_certainly_真。我不認爲在這裏有任何替代方案來看代碼。我可以想出很多方法來啓動一串isends,irecvs,並且讓它們永遠掛起,即使只有一個發送和waitall時代。 – 2011-04-07 23:11:14

+0

那麼你的代碼顯然是錯的地方,我建議你發佈它。 :) – suszterpatt 2011-04-07 23:12:08

+0

感謝您的答覆。該代碼可在https://gist.github.com/909004獲得,因爲它相當長,我認爲它的大部分內容可能相當重要。它試圖轉換一個分佈式矩陣(我知道它可能不是最好的方法來處理它,但我想讓它工作)。 – robintw 2011-04-07 23:32:28

回答

4

當使用MPI_IsendMPI_Irecv時,您必須確保在等待請求完成之前不要修改緩衝區,並且肯定是違反了此操作。如果您將接收器都放入第二個矩陣中,而不是採用適當的方式呢?

另外,global_x2 * global_y2是你的標籤,但我不確定它對於每個send-recieve對都是唯一的,這可能會讓事情變得糟糕。如果將其切換爲發送標籤(global_y2 * global_columns) + global_x2並收到標籤(global_x2 * global_columns) + global_y2會發生什麼情況。

編輯:至於你關於輸出的問題,我假設你是通過在同一臺機器上運行你所有的進程並且只是看標準輸出來測試它。當你這樣做時,即使printf代碼全部在屏障之前執行,你的輸出也會被終端奇怪地緩衝。有兩種方法可以解決這個問題。您可以打印到每個進程的單獨文件,也可以將輸出作爲消息發送到進程0,並讓他執行所有實際打印。

+0

感謝您的回覆。我試過這些(我已經意識到第一個問題了),但他們似乎沒有完全分類。我現在可以在沒有死鎖的情況下運行它,但轉換不能正常進行。我已經改變了這個問題,把代碼的鏈接(現在是這樣)以及我得到的輸出。我對一些事情有點困惑 - 我的障礙似乎並沒有起作用,我想知道是否將(例如)從0排到0的等級,並期望它的工作是一個壞主意。 .. – robintw 2011-04-08 19:18:50