1

Java プログラムを並列化しました。4 コアの Mac では、スレッド数が異なる場合の時間は次のとおりです。

threads #   1         2          4           8          16
time 2597192200 1915988600  2086557400  2043377000  1931178200

ソケットが 2 つあり、それぞれに 4 つのコアがある Linux サーバーで測定された時間は次のとおりです。

threads #   1         2          4           8          16 
time 4204436859 2760602109  1850708620  2370905549  2422668438

ご覧のとおり、高速化は線形の高速化からはほど遠いものです。この場合、同期や I/O 依存などの並列化のオーバーヘッドはほとんどありません。

2 つの質問があります。

  1. これらのデータは、この Java プログラムがメモリにバインドされていることを意味しますか?
  2. もしそうなら、ハードウェアを変更せずにパフォーマンスをさらに改善する方法はありますか?
4

2 に答える 2

1

まあ、彼らはアルゴリズムが CPU バウンドではないことを暗示しています。他の何かによってバインドされている可能性があります-メモリ、I/O、または何かである可能性がありますが、CPU バウンドではない可能性があります。

于 2012-08-17T01:34:31.360 に答える
1

タイトルの質問に答える

アムダールの法則は、プログラムの並列化によって得られる速度向上は、並列化できるプログラムの量に依存することを説明しています。

また、並列処理を調整するためのオーバーヘッドも追加する必要があります。

そのため、プログラムの何パーセント/部分が並列化可能であるか、および発生するオーバーヘッド (同期、通信、偽共有など) を検討します。

読み取りメモリは並列化可能ですか?

ハードドライブから

速度を落とさずに、2 つの異なるハード ディスク ドライブから同時に読み取ることができます。

ただし、通常、並列処理によってハード ドライブからの読み取りが高速化されることはありません。

ハードディスク ドライブ (つまり、ディスクが回転するドライブ) は、順次読み取りを行うように最適化されており、メモリ ロケーション間をジャンプすると、メモリ転送全体が遅くなります。

ソリッド ステート ドライブは実際にはランダムにデータにアクセスし、メモリ内をあちこちジャンプするのが得意です。

RAM とキャッシュから

キャッシュラインの考え方を理解すると、偽共有を避けるのに役立ちます。

このタイプのメモリ操作は、配列を 4 つのパーティションに分割して反復処理するなど、効果的に並列化できます。

あなたの質問

あなたの時間はナノ秒単位であると仮定しているので、コンピューター 1 では、プログラムは 2.5 秒かかり、その後約 2 秒で横ばいになり、ピークは 1.9 秒でした。

最小限のバックグラウンド プログラムを同時に実行し、これらのテストを数回実行して異常を取り除いていただければ幸いです。

また、Java 仮想マシンのジャスト イン タイム コンパイル (JIT) によってタイミングに不規則性が生じる可能性があるため、正確に時間を計るには、コードをループで数回実行し、最後の反復の時間を保存します。 . (またはネイティブ コードにプリコンパイルします)。

また、プログラムが最初に実行されたときから、ハード ドライブから使用されたデータの多くがキャッシュに移動されるため、その後の実行は高速になるはずです。(したがって、ループ後に最後の実行からのタイミングを使用して、メモリがキャッシュにあることを確認するか、最初のタイミングを使用して、タイミングの間にコンピューターの電源をオフにしてからオンにします)。

プログラムはメモリバウンドですか?

あなたのタイミングだけに基づいて、これを言うのは難しい.

最初のコンピューターは 2.5 秒かかり、その後 2 つのスレッドで 20% スピードアップしましたが、その後は約 2.0 秒にとどまりました。

このスピードアップ自体は、JIT とキャッシュ メモリが 1 つのスレッドのタイミングでいっぱいになった結果である可能性があります。その後、実行時間の違いは単なるノイズになる可能性があります。

2 台目のコンピューターは 4.2 秒かかり、次に 2.8 秒、次に 1.9 秒、そして約 2.3 秒に戻りました。

これは、並列処理によるある種のスピードアップを示しているように見えますが、4 スレッドから 8 スレッドへの時間の増加によって示されるように、競合 (メモリ、キャッシュライン、同期など) が発生します。

パフォーマンスを向上させる方法はありますか?

コードでプロファイラーを使用して、コードのどの部分に最も時間がかかっているかを判断します。

(コードをデバッグして中断し、プログラムの場所を確認することで、プロファイラーをシミュレートできます。これを 10 回繰り返して、別の部分よりも比例的に停止している部分があるかどうかを確認します。)

より優れたアルゴリズムを使用するか、メモリ内のデータ (データ構造) を問題に対してより適切な方法で配置します。

問題の並列処理をさらに活用します。

ハード ドライブ メモリの読み取りをシーケンシャルにするようにしてください。おそらく、ハードドライブからの読み取りを行うスレッドが1つだけあり、データを並行キューに入れ、他のスレッドが操作できるようにします。

于 2012-08-17T05:31:43.790 に答える