這些都是我在設計錯誤處理的算法是應該並行運行使用MPI面臨的一些一般性的問題(在C++):我可以在MPI並行代碼中拋出異常嗎?
- 不要例外內部的並行執行代碼的工作?行爲是否定義?
- 它們是如何工作的?這對不同的實現有所不同嗎?
- 這是好的做法 - 還是應該使用返回碼?
這些都是我在設計錯誤處理的算法是應該並行運行使用MPI面臨的一些一般性的問題(在C++):我可以在MPI並行代碼中拋出異常嗎?
異常在MPI代碼中與串行代碼的工作方式相同,但如果在通信器中的所有進程中不會引發異常,或者您可能容易死鎖,則必須非常小心。
MPI_Barrier(comm); /* Or any synchronous call */
if (!rank) throw Exception("early exit on rank=0");
MPI_Barrier(comm); /* rank>0 deadlocks here because rank=0 exited early */
所有的錯誤處理方法都有這個問題,很難從通信器中不一致的錯誤中恢復。在上面的情況下,您可以執行MPI_Allreduce
,以便所有等級都選擇相同的分支。
我的偏好是調用錯誤處理程序並將它們傳播到堆棧上,因爲這往往會給我提供最有用/詳細的錯誤消息,並且很容易捕捉到斷點(或者錯誤處理程序可以將調試程序附加到自身以及發送到您的工作站在xterm)。
無論例外將並行執行過程中發揮作用,取決於你的編譯器和MPI庫實現。如果你想要可移植的行爲,我會避免在這種情況下拋出異常。
如果您想了解的不僅僅是一個數字返回碼錯誤的更多詳細信息,您當然可以返回和/或通過(當然在同一進程中或通過MPI)左右誤差字符串或其他對象。
在理想的世界中,你可以用它們來做你所要求的。對於「理想世界」,我的意思是你可以選擇MPI實現並且能夠自己管理它(而不是說服集羣所有者爲你重新配置它)。例外的最小配置將包括:- 帶例外標誌,可能還有其他幾個。
我最常使用LAM,默認情況下,異常是禁用的。我相信這是其他實現的默認設置。
他們的工作方式與'香草'C++異常相同。他們在並行執行的代碼中工作。
在你的啓動代碼的某個時刻,你希望讓他們:
MPI::COMM_WORLD.Set_errhandler (MPI::ERRORS_THROW_EXCEPTIONS);
(如果你的庫沒有配置爲允許例外,這可能是一個壞主意 - 行爲「不確定」,根據以LAM)
然後:
try { /* something that can fail */ }
catch (MPI::Exception e) {
cout << "Oops: " << e.Get_error_string() << e.Get_error_code();
MPI::COMM_WORLD.Abort (-1) ;
}
至於它是好還是不好的做法,我真的不能說。我還沒有看到MPI黑客編寫的代碼中廣泛使用它們,但這可能是因爲根據我的經驗,代碼通常比C++更具有C語言特性。
錯誤代碼和例外之間的中間地帶可能是錯誤處理,概括地說,你可以指定當一個特定的錯誤(由代碼表示)發生時將被調用的函數。如果您的管理員無法啓用啓用例外,這可能是一種選擇。