タグ付けされた質問 「memory-management」

4
ポータブルマルチコア/ NUMAメモリ割り当て/初期化のベストプラクティス
メモリ帯域幅が制限された計算が共有メモリ環境(OpenMP、Pthreads、またはTBBを介したスレッドなど)で実行される場合、各スレッドがほとんどのメモリに物理的にアクセスするようにメモリを物理メモリに正しく分散させる方法のジレンマがあります「ローカル」メモリバス。インターフェイスは移植性がありませんが、ほとんどのオペレーティングシステムにはスレッドアフィニティを設定する方法があります(たとえばpthread_setaffinity_np()、多くのPOSIXシステム、sched_setaffinity()Linux、SetThreadAffinityMask()Windows)。メモリ階層を決定するためのhwlocなどのライブラリもありますが、残念ながら、ほとんどのオペレーティングシステムにはNUMAメモリポリシーを設定する方法がまだ用意されていません。Linuxは顕著な例外であり、libnumaがありますアプリケーションがページの粒度でメモリポリシーとページ移行を操作できるようにします(2004年以降メインラインにあるため、広く利用可能です)。他のオペレーティングシステムでは、ユーザーが暗黙の「ファーストタッチ」ポリシーに従うことを期待しています。 「ファーストタッチ」ポリシーを使用すると、呼び出し側は、新しく割り当てられたメモリに最初に書き込むときに使用する予定の親和性でスレッドを作成および配布する必要があります。(非常に少数のシステムがあるように構成されているmalloc()、それはちょうど彼らが実際に障害が発生しているときに別のスレッドによって、おそらく、それらを見つけることを約束、実際にページを検索します。)これは、使用してその割り当てを暗示しcalloc()たり、すぐに使用して割り当てが後にメモリを初期化するmemset()ことがフォルトする傾向があるので、有害です割り当てスレッドを実行しているコアのメモリバス上のすべてのメモリ。複数のスレッドからメモリにアクセスすると、最悪のメモリ帯域幅になります。同じことは、new多くの新しい割り当ての初期化を要求するC ++ 演算子にも当てはまります(例:std::complex)。この環境に関するいくつかの観察: 割り当ては「スレッド集合」にすることができますが、異なるスレッドモデルを使用してクライアントと対話しなければならないライブラリ(望ましくはそれぞれ独自のスレッドプール)には望ましくない割り当てがスレッドモデルに混在するようになりました。 RAIIは慣用的なC ++の重要な部分であると考えられていますが、NUMA環境でのメモリパフォーマンスには積極的に有害であるようです。配置newは、malloc()から割り当てられたメモリまたはからのルーチンで使用できますlibnumaが、これにより割り当てプロセスが変更されます(これは必要だと思います)。 編集:演算子に関する私の以前の声明newは間違っていた、それは複数の引数をサポートすることができます、チェタンの応答を参照してください。ライブラリーまたはSTLコンテナーが指定されたアフィニティーを使用することへの懸念がまだあると思います。複数のフィールドがパックされている場合があり、たとえば、std::vector正しいコンテキストマネージャをアクティブにして再割り当てすることを保証するのは不便です。 各スレッドは独自のプライベートメモリを割り当ててフォールトできますが、隣接する領域へのインデックス作成はより複雑になります。(スパース行列ベクトル積の検討行列とベクトルの行パーティションと、の所有されていない部分インデックス作成、xは、より複雑なデータ構造が必要Xは仮想メモリに連続していない)をy← A xy←Aバツy \gets A xバツバツxバツバツx NUMAの割り当て/初期化の解決策は慣用的と見なされますか?他の重要な落とし穴を省きましたか? (C ++の例がその言語に重点を置くことを意味するわけではありませんが、C ++ 言語は、Cのような言語にはないメモリ管理に関するいくつかの決定をエンコードします。物事が異なります。)

4
(方法)メモリの断片化を考慮していますか?
私は有限要素理論の例を使用しますが、大規模なデータ構造を維持し、それを連続的に拡張する人なら誰でも同じようなものを見つけるでしょう。 ポイントと三角形の非構造化メッシュがあり、ポイントが座標(たとえばと)で与えられ、三角形がそれぞれ3つのポイントインデックス(たとえば、jとk)で構成されているとします。バツバツxyyy私私ijjjkkk FEMで一般的なように、メッシュは連続的に細分割されます。グローバルな通常の絞り込みに頼ると、三角形の数は、絞り込みが繰り返されるたびに4倍になります444。これがどのように行われるかに応じて、メモリレイアウトの開発方法は異なります。 メッシュが1〜300のメモリセルを占めているとします。 例1: 新しいメッシュのセル301から1501にスペースを割り当て、そこにリファインされたメッシュのデータを入力して、古いメッシュを忘れます。次のリファインされたメッシュはセル1501〜6300に配置され、次のメッシュは6301〜21500に配置されます。現在のメッシュの場所はメモリ内で「右」に移動しますが、巨大なパッチは使用されません。時期尚早にメモリ不足になる場合があります。 上記の例では、1つのリファインステップの妨げになるだけであることに気づくかもしれません。これは、断片化がなくても、後でリファインメントの合計メモリが不足するためです。頂点配列も考慮されるため、問題はさらに深刻になる可能性があります。 どうすればこれを回避できますか? 例2: 三角形の配列をセル1..1200に再割り当てします。セル1201から2400に新しいメッシュを作成します。その作業コピーの内容をセル1..1200にコピーし、作業コピーを忘れます。同様に繰り返します。 作業コピーが必要なため、まだメモリが不足しています。これはどう: 例3: 三角形の配列をセル1..1500に再割り当てします。古いメッシュを1201 .. 1500にコピーします。セル1..1200に新しいメッシュを作成します。次に、古いメッシュのコピーを忘れます。 これらのスケールではグローバルメッシュリファインメントを使用しないため、ここでのケースは人工的です。増加がはるかに小さい場合、断片化を回避するためにメモリの再調整が可能です。しかしながら、 質問: 実際の科学計算/高性能計算でメモリの断片化が重要になることはありますか? もしそうなら、どうやってそれを避けますか?たぶん私のマシンモデルは間違っているかもしれません、そしていくつかの重い魔法によるOSは暗黙のうちにメモリを再調整するか、ヒープ上の断片化されたブロックを管理します。 具体的には、グリッド管理にどのように影響しますか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.