1

Java プログラムの実行時間に影響を与える可能性のある多くの要因があることを私は知っています。私はそれらのいくつかを排除しようとしました:

  • ウォームアップランは考慮され、カウントされません。
  • System.gc()2 つの実行の間に呼び出されます。

しかし、データは依然として大きく変動することがわかりました。以下は、10 個のスレッドが使用されている場合のサンプルです。

157th run
0 run time: 9106171
1 run time: 9084652
2 run time: 8990820
3 run time: 8989474
5 run time: 9062850
4 run time: 9302010
9 run time: 9454475
8 run time: 9506585
7 run time: 9494990
6 run time: 9491779
total time: 31 ms

158th run
2 run time: 14754858
5 run time: 14865035
0 run time: 15759180
1 run time: 15988056
3 run time: 16660592
8 run time: 16340240
9 run time: 16544479
6 run time: 17280122
7 run time: 17249778
4 run time: 18026322
total time: 19 ms

ほとんどの実行では 17 ~ 20 ミリ秒かかりましたが、5% 未満の実行では 25 ~ 31 ミリ秒かかりました。さらに興味深いことに、後者の場合、各スレッドの実行時間はさらに短くなります。

このプログラムのメイン スレッドstart()join()スレッドのみであり、これ以上の作業はありません。

誰かが考え/ヒントを提供できますか?

4

2 に答える 2

3

スレッドを開始および停止していることに注意してください。テストは非常に短いため、これらのスレッドは 1 つ (または少数) の CPU 配置に割り当てられる時間しかありません。この配置は、より多くのスレッドが一度に実行されることを意味しますが、ハイパースレッディングを使用すると、コアの両方の CPU が使用されます。これが発生すると、各スレッドは (コアやキャッシュなどを共有する必要があるため) 遅くなりますが、スレッド コンテキストの切り替えが減り、コアがより効率的に使用されるため、スループットは向上します。別の配置では、各コアが使用中の CPU が 1 つしかない場合があります。つまり、各スレッドは高速ですが、合計実行時間は長くなります。

ExecutorService を使用してみます。CPU と同じ数のタスク (または複数のタスク) を使用し、スレッドを再利用します。これにより、実行間の一貫性が向上し、OS はより効率的な方法でスレッドを配置する時間ができます。

スレッドをさまざまな CPU レイアウトに割り当てることができるライブラリを作成しました。たとえば、コアを共有するか、共有しないかです。https://github.com/peter-lawrey/Java-Thread-Affinity

于 2012-09-04T07:18:49.823 に答える
1

157 回目の実行では、すべてのスレッドが 1 つのコアで実行されたとします。ボトルネックは、単純に列のようにお互いを待っていることです。個々の実行は、メモリ リソースを単独で管理しているため高速でしたが、すべてが並んで順番を待っていたため、全体としては低速でした。

158 回目の実行が複数のコアに分散していたとしましょう。すべてが一度にメモリ/キャッシュ リソースをめぐって競合するため、各スレッドは個別に時間がかかりました。しかし、彼らはすべて同時に作業していたので、一般的にプロセスはより早く終了しました.

この仮説を検証するには、実行間でスレッドのプールを再利用し、いずれかの方法でアフィニティを手動で設定します。

これは考えられる説明の 1 つに過ぎず、他の要因もある可能性が高く、すべて非常に非決定論的です。たとえば、オペレーティング システムが他のプログラムを同時にスケジュールしている可能性があります (例: cron ジョブ)。

于 2012-09-04T06:12:35.053 に答える