2016-06-09 31 views
1

我有一個可在多個計算節點上運行的大規模代碼,可運行在許多CPU內核上。代碼使用C++並與OpenMPI並行。用於複雜對象的MPI共享內存

我的代碼有一個非常大的對象(〜10GB內存使用量),它是由每個MPI進程讀取的。該對象偶爾會更新(可以通過單個進程完成,只需讀取數據文件即可)。

我到目前爲止一直在做的是給每個MPI過程一個這個對象的副本;但這意味着我受到嚴格的RAM限制,無法使用節點的全部CPU功能。所以,我一直在閱讀有關MPI 3規範中的共享內存。

我的問題是:跨MPI流程共享複雜對象的最佳方式是什麼?在我發現的所有例子中,創建了MPI共享內存窗口並用於交換簡單的數據結構(浮點數,整數數組等等)。我的全局對象是一個自定義類類型,它包含許多成員變量,其中一些是指針,其中許多是其他複雜的類類型。因此,我覺得我不能只調用MPI_Win_allocate_shared並傳遞我複雜對象的地址,特別是因爲我想分享有關成員變量的所有信息(特別是,我想分享基礎值指針類型成員變量 - 即在MPI進程之間共享「深度拷貝」,每個進程中所有虛擬內存地址都是正確的)。

是否有可能通過MPI共享內存實現這種「深度共享」,如果有,是否有這樣做的「最佳實踐」?或者,另一個庫(例如boost進程)是否使這對我更加可行/直接?

P.S.如果我找不到一個好的解決方案,我會採用混合MPI + pthreads方法,我知道我可以在每個節點上用pthreads輕鬆地創建這個全局對象。但我真的希望找到一個優雅的MPI專用解決方案。

+0

指向一個進程的虛擬地址空間的指針在其他進程中沒有意義,除非共享內存映射到完全相同的基址。你想要的並不是不可能實現的:它可以歸結爲在所有進程的所有內存空間中找到一個足夠大的空洞,並且使用首選地址調用mmap(),但既不可移植也不保證每個每次。正確的解決方案是使用相對指針並在取消引用前將基地址添加到每個指針的值。 –

+0

請注意,當底層通信器的進程組跨越多個共享內存節點時,無法使用'MPI_Win_allocate_shared'。在這種情況下,應該使用通常的MPI RMA。 –

+0

我的計劃是像你說的那樣使用RMA爲每個節點獲取一個對象的副本,然後在每個節點上使用共享內存,因此每個節點只有一個對象的副本(這足以保留我的內存使用量最小 - 只需要避免在1個節點上有n個副本。)另外,我正在尋找一個有保證的可移植解決方案(該代碼需要可靠工作,並且理想情況下也應該在Linux和Windows上運行)。當你說「正確的解決方案是...」時,你能否更詳細地解釋這種技術如何解決我的問題?任何僞/示例代碼也會有所幫助。謝謝! – davewy

回答

1

如果您跨越機器邊界(並且您在許多機器上使用節點),沒有任何簡單的方法可以實現您的目標。 如果您僅使用Windows或Linux計算機(而不是混合它們),您可以嘗試將其作爲例如將某些共享資源附加到虛擬內存的方式進行破解(使用系統API以有效的方式執行此操作)。其他方法可以是爲大對象創建自定義序列化/反序列化代碼,並將其作爲二進制數組存儲在內存中(以在同一臺計算機上的進程之間共享)。如果您嘗試存儲「內存轉儲」,則問題是大/小端。如果您使用專用的MPI API,則所有的endian(和數據顯示問題)都可以得到適當的支持。 目前我不確定PVM是否更好地支持這種情況,但在MPI的情況下,我可以在同一臺機器上直接使用虛擬機(僅在進程間共享一些訪問密鑰)...

其他回答1:

在一臺機器上,它應該很簡單,我認爲(您可能使用Windows,所以我現在將專注於此平臺)。在這種情況下,Endian問題和數據對齊無關緊要,因爲我假定您使用相同的選項編譯所有內容(並在相同的硬件上使用)。實現你的目標最簡單的方法是映射到虛擬內存一個正確命名的文件(名稱現在無關緊要,直到你爲不同的對象創建了許多映射 - 在這種情況下,你需要一些命名模式的一致性)。 Sample is here for instance.

創建虛擬內存後,將所有對象數據放在那裏(使用舊學校memcpy或只是所謂的放置構造函數)。如果虛擬內存中已有所有數據,則只需將文件名和一些附加屬性發送到同一臺計算機上的所有進程/節點即可。在虛擬內存空間的開始處,您可以放置​​一些指向對象的指針的數組(例如分配地址變化量),以便輕鬆鏈接所有相關對象(如果您有多個對象)(在這種情況下,vm中的第一個on元素應該包含這樣的數組中的元素 - 這只是一個想法而已)。你可以將你的虛擬內存映射到每個進程的同一個虛擬地址,所以如果你根本不感興趣的話,你不必管理指針:)在這種情況下,不需要任何帶指針的數組!

使用虛擬內存的另外優點是它可以優化內存頁的使用情況,所以如果您有這樣的大數據對象,它不會吞下10GB的內存。

順便說一句:Windows支持直接內存頁面與部分switch共享。在CPP中,您有such support

+0

讓我們假設爲了簡單起見,我只在一臺機器上工作。 (對於多臺機器,我會做類似上面提到的Hristo,使用RMA爲每個節點獲取一個對象的副本,然後使用共享內存在該節點上的所有特效之間共享該副本。)如果我只在一個節點上,你能否進一步解釋你的二進制數組解決方案將如何工作?我如何獲得全球地址並將數據存儲在那裏?我將如何將它轉換成我想要的類型? – davewy

+0

我在「附加答案1」部分下添加了答案:) 希望很清楚我的想法是什麼...... –