(あなたの問題に対する可能な解決策は最後の段落です)
仮想メモリを備えた最新のオペレーティングシステムでのメモリ割り当ては、2段階のプロセスです。まず、プロセスの仮想アドレス空間の一部が予約され、VmSize
それに応じてプロセスの仮想メモリサイズ()が増加します。これにより、いわゆるプロセスページテーブルにエントリが作成されます。ページは最初は物理メモリフレームに関連付けられていません。つまり、物理メモリは実際には使用されていません。この割り当てられた部分の一部が実際に読み取られたり書き込まれたりするたびに、ページフォールトが発生し、オペレーティングシステムが物理メモリから空きページをインストール(マップ)します。これにより、プロセスの常駐セットサイズが増加します(VmRSS
)。他のプロセスがメモリを必要とする場合、OSは、使用頻度の低いページ(「使用頻度の低いページ」の定義は実装に大きく依存します)のコンテンツを永続ストレージ(ほとんどの場合ハードドライブ、または通常はスワップデバイス)に保存する場合があります。 )そしてマップを解除します。このプロセスによりRSSは減少しますが、VmSize
そのまま残ります。このページに後でアクセスすると、ページフォールトが再度発生し、元に戻されます。仮想メモリのサイズは、仮想メモリの割り当てが解放されたときにのみ減少します。VmSize
メモリマップトファイル(つまり、実行可能ファイルとそれがリンクするすべての共有ライブラリまたは他の明示的にマップされたファイル)と共有メモリブロックもカウントされることに注意してください。
プロセスには、静的に割り当てられたメモリとヒープメモリの2つの一般的なタイプのメモリがあります。静的に割り当てられたメモリは、すべての定数とグローバル/静的変数を保持します。これはデータセグメントの一部であり、そのサイズはVmData
メトリック。データセグメントは、動的メモリが割り当てられているプログラムヒープの一部もホストします。データセグメントは連続的です。つまり、特定の場所から始まり、スタックに向かって上向きに成長します(非常に高いアドレスから始まり、その後下向きに成長します)。データセグメントのヒープの問題は、隣接するデータセグメントをより小さなメモリチャンクに分割する処理を行う特別なヒープアロケータによって管理されることです。一方、Linuxでは、仮想メモリを直接マッピングすることで動的メモリを割り当てることもできます。これは通常、メモリを節約するために大規模な割り当てに対してのみ実行されます。これは、ページサイズの倍数(通常は4 KiB)のメモリしか割り当てられないためです。
スタックは、特に大きなアレイが自動(スタック)ストレージに割り当てられている場合、大量のメモリ使用量の重要な原因にもなります。スタックは、使用可能な仮想アドレス空間の最上部近くから始まり、下に向かって成長します。場合によっては、データセグメントの先頭に到達したり、他の仮想割り当ての最後に到達したりする可能性があります。その時、悪いことが起こります。スタックサイズは、VmStack
メトリックとで考慮されVmSize
ます。それを次のように要約することができます:
VmSize
すべての仮想メモリ割り当て(ファイルマッピング、共有メモリ、ヒープメモリ、その他のメモリ)を考慮し、新しいメモリが割り当てられるたびに増加します。ほとんどの場合、データセグメント内の解放された古い割り当ての代わりに新しいヒープメモリの割り当てが行われると、新しい仮想メモリは割り当てられません。仮想割り当てが解放されるたびに減少します。VmPeak
の最大値を追跡しますVmSize
-時間の経過とともに増加する可能性があります。
VmRSS
メモリがアクセスされると増加し、メモリがスワップデバイスにページアウトされると減少します。
VmData
ヒープのデータセグメント部分が利用されるにつれて大きくなります。現在のヒープアロケータは、将来の割り当てで必要になった場合に備えて、解放されたメモリを保持するため、縮小することはほとんどありません。
InfiniBandまたは他のRDMAベースのファブリックを備えたクラスターで実行している場合は、別の種類のメモリ(ロックされた(レジスタード)メモリ(VmLck
))が機能します。これは、ページアウトが許可されていないメモリです。どのように拡大および縮小するかは、MPIの実装によって異なります。すでに登録されているブロックの登録を解除しないものもあれば(複雑すぎてここで説明できない理由に関する技術的な詳細)、仮想メモリマネージャーをより適切に使用するために登録を解除するものもあります。
あなたの場合、仮想メモリのサイズ制限に達していると言います。これは、この制限の設定が低すぎるか、OSによって課せられた制限に達していることを意味している可能性があります。まず、Linux(およびほとんどのUnix)には、ulimit
メカニズムを通じて人為的な制限を課す手段があります。シェルで実行ulimit -v
すると、KiBでの仮想メモリサイズの制限がわかります。を使用して制限を設定できますulimit -v <value in KiB>
。これは、現在のシェルとその子、孫などによって生成されたプロセスにのみ適用されます。あなたは指示する必要がありますmpiexec
(またはmpirun
)リモートノードで起動する場合は、この値を他のすべてのプロセスに伝播します。LSF、Sun / Oracle Grid Engine、Torque / PBSなどのワークロードマネージャの制御下でプログラムを実行している場合、仮想メモリのサイズ制限を制御するジョブパラメータがあります。最後になりましたが、32ビットプロセスは通常、2GiBの使用可能な仮想メモリに制限されています。