9

32 コアの Opteron マシンを購入したばかりですが、得られるスピードアップには少しがっかりしています。約 24 スレッドを超えると、スピードアップがまったく見られず (実際には全体的に遅くなります)、約 6 スレッドを過ぎると、大幅にサブリニアになります。

私たちのアプリケーションは非常にスレッド フレンドリーです。私たちのジョブは約 170,000 の小さなタスクに分割され、それぞれが 5 ~ 10 秒で個別に実行できます。それらはすべて、サイズが約 4Gb の同じメモリ マップト ファイルから読み取ります。ときどき書き込みを行いますが、書き込みごとに 10,000 回の読み取りが必要になる場合があります。170,000 個のタスクのそれぞれの最後に、ほんの少しのデータを書き込むだけです。書き込みはロック保護されています。プロファイリングは、ロックが問題ではないことを示しています。スレッドは、非共有オブジェクトごとに大量の JVM メモリを使用し、共有 JVM オブジェクトへのアクセスはほとんど行わず、書き込みを伴うアクセスはごくわずかです。

NUMA を有効にして、Linux 上の Java でプログラミングしています。128GbのRAMがあります。それぞれ 16 コアの 2 つの Opteron CPU (モデル 6274) があります。各 CPU には 2 つの NUMA ノードがあります。Intel クアッドコア (つまり 8 コア) で実行されている同じジョブは、最大 8 スレッドまでほぼ直線的にスケーリングされました。

ほとんどのルックアップが NUMA ノードに対してローカルになることを期待して、スレッドごとに 1 つになるように読み取り専用データを複製しようとしましたが、これによるスピードアップは見られませんでした。

32 スレッドの場合、「top」は、CPU の 74% が「us」(ユーザー) で、約 23% が「id」(アイドル) であることを示しています。しかし、スリープはなく、ディスク I/O はほとんどありません。24 スレッドの場合、CPU 使用率は 83% になります。「アイドル」状態を解釈する方法がわかりません。これは「メモリ コントローラーを待機中」という意味ですか?

NUMA のオンとオフを切り替えてみましたが (リブートが必要な Linux レベルの設定について言及しています)、違いは見られませんでした。NUMA が有効になっている場合、「numastat」は「割り当てとアクセスのミス」の約 5% のみを示しました (キャッシュ ミスの 95% は NUMA ノードに対してローカルでした)。[編集:] しかし、"-XX:+useNUMA" を Java コマンドライン フラグとして追加すると、10% のブーストが得られました。

私たちが持っている 1 つの理論は、アプリケーションが大量の RAM を使用し、多くのキャッシュ ミスがあると考えているため、メモリ コントローラーを使い果たしているというものです。

(a) プログラムを高速化して線形スケーラビリティに近づけるか、(b) 何が起こっているかを診断するにはどうすればよいでしょうか?

また: (c) 「トップ」の結果をどのように解釈すればよいですか? 「アイドル」は「メモリ コントローラーでブロックされている」という意味ですか? (d) Opteron と Xeon の特性に違いはありますか?

4

5 に答える 5

2

その答えは、ハードウェア アーキテクチャの検討にあると確信しています。マルチコア コンピュータは、ネットワークで接続された個々のマシンであるかのように考える必要があります。実際、Hypertransport と QPI はこれですべてです。

これらのスケーラビリティの問題を解決するには、共有メモリの観点から考えるのをやめ、Communicating Sequential Processes の哲学を採用し始める必要があることがわかりました。つまり、ハードウェアがネットワークで接続された 32 個のシングル コア マシンである場合、ソフトウェアをどのように作成するかを想像してください。現代の (そして古代の) CPU アーキテクチャは、あなたが求めているような自由なスケーリングを提供するようには設計されていません。それらは、多くの異なるプロセスが独自のデータを処理できるように設計されています。

コンピューティングの他のすべてと同様に、これらのことは流行に乗っています。CSP の歴史は 1970 年代にさかのぼりますが、Java から派生した最新の Scala は、この概念を具体化したものとして人気があります。ウィキペディアの Scala 同時実行に関するこのセクションを参照してください。

CSP の哲学が行うことは、データと解決しようとしている問題に適合するデータ分散スキームを設計することを強制することです。これは必ずしも簡単なことではありませんが、それを管理できれば、非常にうまく拡張できるソリューションを手に入れることができます。Scala を使用すると、開発が容易になる場合があります。

個人的には、すべて CSP と C で行っています。これにより、8 コアから数千コアまで完全に直線的にスケーリングする信号処理アプリケーションを開発することができました (限界は私の部屋の大きさです)。

最初に行う必要があるのは、実際に NUMA を使用することです。オンにするのは魔法の設定ではありません。ソフトウェアのアーキテクチャでそれを活用する必要があります。Javaについてはわかりませんが、Cでは、メモリ割り当てを特定のコアのメモリコントローラー(別名メモリアフィニティ)にバインドし、OSがヒントを取得しない場合はスレッド(コアアフィニティ)にも同様にバインドします。

あなたのデータは 32 個のきちんとした個別のチャンクに分解されていないと思いますか? プログラムに内在するデータ フローを正確に知らずにアドバイスを与えることは困難です。しかし、データフローの観点から考えてみてください。平らに引き抜きます。これには、データ フロー ダイアグラムが役立ちます (もう 1 つの古くからあるグラフィカルな形式表記法)。あなたの写真が単一のオブジェクトを通過するすべてのデータを示している場合 (例えば、単一のメモリ バッファを通過する場合)、遅くなります...

于 2013-04-10T21:50:04.937 に答える
1

ロックを最適化し、同期を最小限に抑えたと仮定します。このような場合でも、並列プログラミングに使用しているライブラリに大きく依存します。

同期の問題がなくても発生する可能性のある問題の 1 つは、メモリ バスの輻輳です。これは非常に厄介で、取り除くのが困難です。私が提案できるのは、どうにかしてタスクを大きくし、作成するタスクを少なくすることだけです。これは、問題の性質に大きく依存します。理想的には、コア/スレッドの数と同じ数のタスクが必要ですが、これを達成するのは (可能であれば) 簡単ではありません。

他に役立つことは、JVM により多くのヒープを与えることです。これにより、ガベージ コレクターを頻繁に実行する必要が減り、速度が少し向上します。

「アイドル」は「メモリコントローラーでブロックされている」ことを意味しますか

いいえ、上には表示されません。CPU がメモリ アクセスを待機している場合、CPU はビジーとして表示されます。アイドル期間がある場合は、ロックまたは IO を待っています。

于 2012-11-30T13:26:50.563 に答える