簡體   English   中英

MPI_SEND占據了虛擬內存的很大一部分

[英]MPI_SEND takes huge part of virtual memory

在大量內核上調試我的程序,我遇到了insufficient virtual memory非常奇怪的錯誤。 我的調查導致代碼的和平,主機向每個從機發送小消息。 然后我寫了一個小程序,其中1個master只用MPI_SEND發送10個整數,所有從站用MPI_RECV接收它。 MPI_SEND之前和之后的文件/proc/self/status MPI_SEND表明,內存大小之間的差異是巨大的! 最有趣的事情(崩潰我的程序)是,這個內存在MPI_Send之后不會釋放,並且仍然需要占用大量空間。

有任何想法嗎?

 System memory usage before MPI_Send, rank: 0
Name:   test_send_size                                                                                
State:  R (running)                                                                                  
Pid:    7825                                                                                           
Groups: 2840                                                                                        
VmPeak:   251400 kB                                                                                 
VmSize:   186628 kB                                                                                 
VmLck:        72 kB                                                                                  
VmHWM:      4068 kB                                                                                  
VmRSS:      4068 kB                                                                                  
VmData:    71076 kB                                                                                 
VmStk:        92 kB                                                                                  
VmExe:       604 kB                                                                                  
VmLib:      6588 kB                                                                                  
VmPTE:       148 kB                                                                                  
VmSwap:        0 kB                                                                                 
Threads:    3                                                                                          

 System memory usage after MPI_Send, rank 0
Name:   test_send_size                                                                                
State:  R (running)                                                                                  
Pid:    7825                                                                                           
Groups: 2840                                                                                        
VmPeak:   456880 kB                                                                                 
VmSize:   456872 kB                                                                                 
VmLck:    257884 kB                                                                                  
VmHWM:    274612 kB                                                                                  
VmRSS:    274612 kB                                                                                  
VmData:   341320 kB                                                                                 
VmStk:        92 kB                                                                                  
VmExe:       604 kB                                                                                  
VmLib:      6588 kB                                                                                  
VmPTE:       676 kB                                                                                  
VmSwap:        0 kB                                                                                 
Threads:    3        

這是幾乎任何在InfiniBand上運行的MPI實現的預期行為。 IB RDMA機制要求應該注冊數據緩沖區,即它們首先被鎖定在物理內存中的固定位置,然后驅動程序告訴InfiniBand HCA如何將虛擬地址映射到物理內存。 這是非常復雜的,因此注冊內存以供IB HCA使用的過程非常緩慢 ,這就是為什么大多數MPI實現永遠不會注冊曾經注冊的內存,希望以后將相同的內存再次用作源或數據目標。 如果已注冊的內存是堆內存,則它永遠不會返回到操作系統,這就是為什么您的數據段只會增大。

盡可能重用發送和接收緩沖區。 請記住,通過InfiniBand進行通信會導致高內存開銷。 大多數人並沒有真正考慮這個問題,而且通常記錄很少,但InfiniBand使用了許多特殊的數據結構(隊列),這些結構在進程的內存中分配,並且這些隊列隨着進程的數量而顯着增長。 在一些完全連接的情況下,隊列內存的數量可能很大,以至於實際上沒有為應用程序留下任何內存。

有一些參數可以控制英特爾MPI使用的IB隊列。 在您的情況下,最重要的是I_MPI_DAPL_BUFFER_NUM ,它控制預分配和預注冊內存的數量。 它的默認值是16 ,所以你可能想減少它。 但請注意可能的性能影響。 您還可以通過將I_MPI_DAPL_BUFFER_ENLARGEMENT設置為1來嘗試使用動態預分配緩沖區大小。 啟用此選項后,Intel MPI最初會注冊小緩沖區,如果需要,稍后會增加它們。 另請注意,IMPI會延遲打開連接,這就是為什么只有在調用MPI_Send之后才會看到使用內存大幅增加的原因。

如果不使用DAPL運輸,例如,使用ofa運輸代替,沒有太多可以做的。 您可以通過將I_MPI_OFA_USE_XRC設置為1來啟用XRC隊列。 這應該以某種方式減少使用的內存。 如果程序的通信圖形未完全連接(完全連接的程序是每個級別與所有其他級別對話的程序),則通過將I_MPI_OFA_DYNAMIC_QPS設置為1來啟用動態隊列對創建可能會降低內存使用量。

Hristo的答案大多是正確的,但由於你使用的是小消息,所以有一點不同。 消息最終出現在急切路徑上:它們首先被復制到已經注冊的緩沖區,然后該緩沖區用於傳輸,接收方將消息從其末端的急切緩沖區中復制出來。 在代碼中重用緩沖區只會有助於處理大型郵件。

這樣做是為了避免注冊用戶提供的緩沖區的速度慢。 對於大型消息,副本比注冊時間更長,因此使用集合協議。

這些急切的緩沖區有點浪費。 例如,默認情況下,它們在具有OF動詞的英特爾MPI上為16kB。 除非使用消息聚合,否則每個10-int大小的消息正在占用4個4kB頁面。 但無論如何,在與多個接收器通信時,聚合將無濟於事。

那么該怎么辦? 減少熱切緩沖區的大小。 這可以通過設置eager / rendezvous閾值( I_MPI_RDMA_EAGER_THRESHOLD環境變量)來控制。 嘗試2048甚至更小。 請注意,這可能會導致延遲增加。 或者更改I_MPI_DAPL_BUFFER_NUM變量以控制這些緩沖區的數量,或者嘗試Hristo建議的動態調整大小功能。 假設您的IMPI正在使用DAPL(默認值)。 如果直接使用OF動詞,則DAPL變量將不起作用。


編輯:因此,要使其運行的最終解決方案是設置I_MPI_DAPL_UD=enable 我可以推測魔法的起源,但我無法訪問英特爾的代碼來實際證實這一點。

IB可以具有不同的傳輸模式,其中兩個是RC(可靠連接)和UD(不可靠數據報)。 RC需要主機之間的顯式連接(如TCP),並且每個連接花費一些內存。 更重要的是,每個連接都有與之相關的急切緩沖區,這確實加起來了。 這是英特爾默認設置的結果。

可以進行優化:在連接之間共享急切緩沖區(這稱為SRQ - 共享接收隊列)。 還有一個名為XRC(擴展RC)的Mellanox擴展,它進一步實現了隊列共享:在同一節點上的進程之間。 默認情況下,Intel的MPI通過DAPL訪問IB設備,而不是直接通過OF動詞訪問IB設備。 我的猜測是這排除了這些優化(我沒有DAPL的經驗)。 通過設置I_MPI_FABRICS=shm:ofa I_MPI_OFA_USE_XRC=1I_MPI_OFA_USE_XRC=1 (使英特爾MPI使用OFA接口而不是DAPL),可以啟用XRC支持。

當您切換到UD傳輸時,您可以在緩沖區共享的基礎上進一步優化:不再需要跟蹤連接。 緩沖區共享在此模型中很自然:由於沒有連接,所有內部緩沖區都在共享池中,就像SRQ一樣。 因此可以節省更多內存,但需要付出代價:數據報交付可能會失敗,並且由軟件而不是IB硬件來處理重新傳輸。 當然,這對使用MPI的應用程序代碼都是透明的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM