7

ショートバージョンはタイトルにあります。

長いバージョン: Java を使用して科学的最適化のためのプログラムに取り組んでいます。プログラムのワークロードは、並列フェーズと直列フェーズに分けることができます。並列フェーズとは、高度に並列化可能な作業が実行されていることを意味します。プログラムを高速化するために (数時間または数日間実行されます)、使用しているマシンの CPU コアの数 (通常は 4 または 8) に等しい数のスレッドを作成し、それらの間で作業を分割します。次に、これらのスレッドを開始して join() してから、シリアル フェーズに進みます。

ここまでは順調ですね。私を悩ませているのは、並列フェーズの CPU 使用率とスピードアップが「理論上の最大値」にほど遠いことです。たとえば、4 つのコアがある場合、「使用率」は 350 ~ 400% になると予想されます (top で報告されているように)。代わりに、180 から約 310 の間で跳ね返ります。1 つのスレッドのみを使用すると、100% の CPU 使用率が得られます。

スレッドがフルスピードで実行されない唯一の理由は次のとおりです。 - I/O によるブロッキング - 同期によるブロッキング

並列スレッドでは I/O はまったく行われておらず、同期も行われていません。スレッドによって共有される唯一のデータ構造は読み取り専用であり、基本型または (非同時) コレクションのいずれかです。だから私は他の説明を探しています。1 つの可能性として、複数のスレッドがガベージ コレクションのために繰り返しブロックしている可能性がありますが、それはメモリ プレッシャーのある状況でのみ意味があるように思われ、必要な最大ヒープ領域をはるかに超えて割り当てています。

任意の提案をいただければ幸いです。

更新:誰かが興味を持っている場合に備えて、さらに調査した後、一般的なパフォーマンスのためにコードを微調整し、同期とは何の関係もありませんが、使用率が向上していることを確認しました。ただし、いくつかの変更により、特に新しいヒープ割り当てが少なくなるはずでした。イテレータ一時的なボックス化された数値の使用をいくつか取り除きました (ハイパフォーマンス Java コンピューティング用の CERN "Colt" ライブラリは、ここで役立ちました: IntArrayList のようなコレクションを提供します)。 、基本型の DoubleArrayList など)。したがって、おそらくガベージコレクションが原因だと思います。

4

7 に答える 7

5

すべてのグラフィック操作は、Swing 内の単一のスレッドで実行されます。それらが画面にレンダリングされている場合、事実上、このスレッドへのアクセスをめぐって競合します。

Windows で実行している場合、すべてのグラフィック操作は、何があっても単一のスレッドで実行されます。他のオペレーティング システムにも同様の制限があります。

スレッド化されたワーカーの適切な粒度を取得することは、実際にはかなり難しい場合があり、場合によっては簡単に大きすぎたり小さすぎたりすることがあります。これにより、通常、すべてのコアの使用率が 100% 未満になります。

多くの GUI をレンダリングしていない場合、最も可能性の高い原因は、共有リソースに対して思っている以上に競合していることです。これは、jprofiler などのプロファイラー ツールで簡単に確認できます。bea の jrockit のような一部の VM は、これをすぐに利用できるようにすることさえできます。

これは、推測に基づいて行動したくない場所の 1 つです。プロファイラーを手に入れよう!

于 2008-12-02T07:54:54.337 に答える
4

まず第一に、GC は「メモリ不足の状況」でのみ発生するのではなく、JVM が適切と判断したときにいつでも発生します (私が知る限り、予測できません)。

第二に、スレッドがヒープにメモリを割り当てる場合 (コレクションを使用すると述べているので、ヒープにメモリを割り当てていると思います)、このメモリが現在 RAM にあるのか、仮想メモリ ページにあるのかはわかりません (OS が決定します)。 )、したがって、「メモリ」へのアクセスにより、ブロッキング I/O アクセスが発生する可能性があります。

最後に、以前の回答で示唆されているように、プロファイラーを使用して何が起こるかを確認すると便利な場合があります (または、JMX 監視でさえもヒントが得られる場合があります)。

より具体的な (コード) 情報を提供しない限り、問題に関するさらなるヒントを得るのは難しいと思います。

于 2008-12-02T08:46:16.013 に答える
2

まず、このボックスに関して他に重要な作業を行っていないと仮定します。もしそうなら、それは明らかに物事を混乱させるでしょう。

本当に何も共有していないとしたら、それは非常に奇妙に聞こえます。コードが実際に何をしているのか、もっと詳しく教えていただけますか?

プログラムの n 個のコピーを異なる Java プロセスとして実行し、それぞれが単一のスレッドのみを使用するとどうなるでしょうか? それが各 CPU を完全に使用する場合、少なくとも OS の問題ではないことがわかります。OS といえば、これが実行されているのはどれで、どの JVM ですか? さまざまな JVM やさまざまな OS を試すことができれば、結果から何が問題なのかのヒントが得られるかもしれません。

于 2008-12-02T09:11:34.307 に答える
1

また重要なポイント: どのハードウェアを使用していますか? たとえば、4 ~ 8 コアは、Suns Niagara CPU の 1 つで作業することを意味します。また、コアが 4 ~ 8 個あるにもかかわらず、FPUが少なくなっています。科学的なものを計算するとき、FPU がボトルネックになることがあります。

于 2008-12-02T09:17:24.560 に答える
0

計算に CPU の全機能を使用しようとしますが、OS 自体もリソースを使用します。そのため、OS はニーズを満たすために一部の実行をブロックすることに注意してください。

于 2008-12-02T09:03:03.483 に答える
0

JRockit Mission Control に付属のレイテンシ アナライザを試してください。アプリケーションがファイル I/O、TLA フェッチ、オブジェクト割り当て、スレッド中断、JVM ロック、gc 一時停止などを待機している場合、CPU が何もしていないときに CPU が何をしているかを示します。遷移も表示できます。 、たとえば、あるスレッドが別のスレッドを起動したとき。オーバーヘッドはごくわずかで、1% 程度です。

詳細については、このブログを参照してください。このツールは無料で開発に使用でき、ここからダウンロードできます

于 2008-12-10T02:33:16.010 に答える
0

あるレベルで同期を行っています。

おそらく、ガベージ コレクションを含むメモリ割り当てシステムでのみです。JVM ベンダーは、これらの領域でのブロッキングを最小限に抑えるよう取り組んできましたが、ゼロにすることはできません。おそらく、あなたのアプリケーションの何かが、この領域の弱点を突いているのでしょう。

受け入れられている知恵は、「独自のメモリ回収プールを構築しないでください。GC に任せてください」です。これはほとんどの場合に当てはまりますが、私が管理している少なくとも 1 つのコードではそうではありません (プロファイリングで証明されています)。おそらく、何らかの主要な方法でオブジェクトの割り当てをやり直す必要があります。

于 2008-12-04T20:10:58.920 に答える