7

多数のカーネルでプログラムをデバッグすると、非常に奇妙なエラーが発生しinsufficient virtual memoryました。私の調査はコードの平和につながり、マスターは各スレーブに小さなメッセージを送信します。次に、1 つのマスターが 10 個の整数を単純に送信しMPI_SEND、すべてのスレーブがそれを受信する小さなプログラムを作成しましたMPI_RECV/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        
4

2 に答える 2

10

これは、InfiniBand で実行されるほぼすべての MPI 実装で予想される動作です。IB RDMA メカニズムでは、データ バッファーを登録する必要があります。つまり、データ バッファーは最初に物理メモリ内の固定位置にロックされ、次にドライバーが InfiniBand HCA に仮想アドレスを物理メモリにマップする方法を指示します。IB HCA で使用するためにメモリを登録するプロセスは非常に複雑であり、したがって非常に時間がかかります。そのため、ほとんどの MPI 実装では、同じメモリが後でソースまたはデータ ターゲットとして再び使用されることを期待して、一度登録されたメモリを登録解除することはありません。登録されたメモリがヒープ メモリであった場合、オペレーティング システムに返されることはありません。そのため、データ セグメントのサイズが大きくなるだけです。

送信バッファと受信バッファを可能な限り再利用します。InfiniBand を介した通信では、高いメモリ オーバーヘッドが発生することに注意してください。ほとんどの人はこれについてあまり考えておらず、通常は文書化も不十分ですが、InfiniBand はプロセスのメモリに割り当てられる多くの特別なデータ構造 (キュー) を使用し、それらのキューはプロセスの数とともに大幅に増加します。一部の完全に接続されたケースでは、キュー メモリの量が非常に大きくなり、実際にはアプリケーション用にメモリが残らないことがあります。

Intel 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に設定することにより、XRC キューを使用可能にすることができます1。これにより、使用されるメモリが何らかの形で減少するはずです。I_MPI_OFA_DYNAMIC_QPSまた、 に設定して動的キュー ペアの作成を有効にする1と、プログラムの通信グラフが完全に接続されていない場合 (完全に接続されたプログラムとは、各ランクが他のすべてのランクと通信するプログラムです)、メモリ使用量が減少する可能性があります。

于 2012-10-26T15:20:17.627 に答える
5

Hristoの答えはほとんど正しいですが、小さなメッセージを使用しているため、少し違いがあります. メッセージは最初に登録済みのバッファーにコピーされ、次にそのバッファーが転送に使用され、受信者はメッセージを最後に熱心なバッファーからコピーします。コード内でバッファを再利用しても、大きなメッセージの場合にのみ役立ちます。

これは、ユーザーが指定したバッファーの登録の遅さを避けるために正確に行われます。大きなメッセージの場合、登録よりもコピーに時間がかかるため、代わりにランデブー プロトコルが使用されます。

これらの積極的なバッファは、やや無駄です。たとえば、OF 動詞を使用する Intel MPI では、デフォルトで 16kB です。メッセージ アグリゲーションが使用されない限り、サイズが 10 int の各メッセージは 4 つの 4kB ページを消費します。ただし、とにかく複数の受信者と話す場合、集約は役に立ちません。

じゃあ何をすればいいの?イーガー バッファのサイズを減らします。これは、熱心/ランデブーのしきい値 (I_MPI_RDMA_EAGER_THRESHOLD環境変数) を設定することによって制御されます。2048 以下を試してください。これにより、レイテンシが増加する可能性があることに注意してください。または、I_MPI_DAPL_BUFFER_NUM変数を変更してこれらのバッファーの数を制御するか、Hristo が提案した動的サイズ変更機能を試してください。これは、IMPI が DAPL (デフォルト) を使用していることを前提としています。OF 動詞を直接使用している場合、DAPL 変数は機能しません。


編集:これを実行するための最終的な解決策は、設定I_MPI_DAPL_UD=enableでした。魔法の起源を推測することはできますが、これを実際に確認するための Intel のコードにアクセスすることはできません。

IB はさまざまなトランスポート モードを持つことができます。そのうちの 2 つは RC (Reliable Connected) と UD ​​(Unreliable Datagram) です。RC ではホスト間の明示的な接続 (TCP など) が必要であり、接続ごとにいくらかのメモリが消費されます。さらに重要なことに、各接続には熱心なバッファが関連付けられており、これは実際に合計されます。これは、インテルのデフォルト設定で得られるものです。

可能な最適化があります: 接続間で熱心なバッファを共有します (これは SRQ - 共有受信キューと呼ばれます)。XRC (eXtended RC) と呼ばれるさらに Mellanox 専用の拡張機能があり、同じノード上のプロセス間でキューをさらに共有します。デフォルトでは、Intel の MPI は、OF 動詞を介して直接アクセスするのではなく、DAPL を介して IB デバイスにアクセスします。私の推測では、これによりこれらの最適化が妨げられます (私は DAPL の経験がありません)。I_MPI_FABRICS=shm:ofaとを設定することで XRC サポートを有効にすることができますI_MPI_OFA_USE_XRC=1(Intel MPI が DAPL の代わりに OFA インターフェイスを使用するようにします)。

UD トランスポートに切り替えると、バッファー共有に加えてさらに最適化されます。接続を追跡する必要がなくなります。このモデルではバッファー共有は自然です。接続がないため、すべての内部バッファーは SRQ と同様に共有プールにあります。そのため、さらにメモリを節約できますが、コストがかかります。データグラムの配信が失敗する可能性があり、再送信を処理するのは IB ハードウェアではなく、ソフトウェア次第です。もちろん、これは MPI を使用するアプリケーション コードに対してすべて透過的です。

于 2012-10-26T15:40:25.407 に答える