web-dev-qa-db-ja.com

スレッドプールの理想的なサイズの設定

違いは何ですか-

newSingleThreadExecutor vs newFixedThreadPool(20)

オペレーティングシステムとプログラミングの観点から。

newSingleThreadExecutorを使用してプログラムを実行しているときはいつでも、私のプログラムは非常にうまく機能し、エンドツーエンドのレイテンシ(95パーセンタイル)は_5ms_になります。

しかし、私が使用してプログラムを実行し始めるとすぐに

newFixedThreadPool(20)

プログラムのパフォーマンスが低下し、エンドツーエンドのレイテンシが_37ms_として表示され始めます。

だから今私はアーキテクチャの観点からスレッドの数が何を意味するのかを理解しようとしていますか?また、選択する必要があるスレッドの最適な数はどのように決定するのですか?

そして、より多くのスレッドを使用している場合、どうなりますか?

誰かがこれらの簡単なことを平易な言葉で説明してくれるなら、それは私にとって非常に役に立ちます。助けてくれてありがとう。

私のマシン構成仕様-Linuxマシンからプログラムを実行しています-

_processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
stepping        : 7
cpu MHz         : 2599.999
cache size      : 20480 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc Arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln pts
bogomips        : 5199.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
stepping        : 7
cpu MHz         : 2599.999
cache size      : 20480 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc Arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln pts
bogomips        : 5199.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:
_
26
arsenal

OK。理想的には、スレッドが互いにロックしないようにロックされていない(互いに独立している)と想定し、作業負荷(処理)が同じであると想定できる場合、プールサイズはRuntime.getRuntime().availableProcessors()またはavailableProcessors() + 1が最良の結果を与えます。

しかし、スレッドが互いに干渉したり、I/Oが関与したりした場合、Amadhalの法則はかなりよく説明されます。 wikiから、

アムダールの法則によれば、Pが並列化できる(つまり、並列化のメリットがある)プログラムの割合であり、(1 − P)が並列化できない(直列のままである)割合である場合、 N個のプロセッサを使用して実現

Amadhal law

あなたの場合、利用可能なコアの数とそれらが正確に何をするかに基づいて(純粋な計算?I/O?ホールドロック?あるリソースに対してブロックされている?など)、上記に基づいたソリューションを考え出す必要がありますパラメーター。

例:数か月前、私は数値のWebサイトからデータを収集することに関与していました。私のマシンは4コアで、プールサイズは4でした。しかし、操作は純粋にI/Oであり、ネット速度はまともだったので、プールサイズ7で最高のパフォーマンスが得られることに気付きました。そしてそれは、スレッドが計算能力のために戦っていたのではなく、I/Oのために戦っていたからです。したがって、より多くのスレッドがコアを積極的に争うことができるという事実を活用できます。

追伸:本の「パフォーマンス」の章に目を通すことをお勧めします-Java Brian Goetzによる並行性の実践。このような問題を詳細に扱います。

42
Jatin

だから今私はアーキテクチャの観点からスレッドの数が何を意味するのかを理解しようとしていますか?

各スレッドには、独自のスタックメモリ、プログラムカウンター(次に実行する命令へのポインターなど)、およびその他のローカルリソースがあります。それらを交換すると、単一のタスクのレイテンシが損なわれます。利点は、1つのスレッドがアイドル状態の間(通常は入出力を待機しているとき)、別のスレッドが作業を完了できることです。また、複数のプロセッサが利用可能な場合、リソースがなく、タスク間でロックの競合がない場合、それらは並列に実行できます。

また、選択する必要があるスレッドの最適な数はどのように決定するのですか?

スワップ価格とアイドル時間を回避する機会の間のトレードオフは、タスクがどのように見えるかの詳細(I/Oの量、およびI/O間の作業量とメモリの使用量)によって異なりますコンプリート)。実験が常に鍵となります。

そして、より多くのスレッドを使用している場合、どうなりますか?

通常、最初はスループットが直線的に増加し、次に比較的平坦な部分があり、次に低下します(これはかなり急な場合があります)。システムはそれぞれ異なります。

5
Mel Nicholson

アムダールの法則を見ると、特にPとNの大きさが正確にわかっている場合は問題ありません。これが実際に発生することはないため、パフォーマンスを監視し(とにかくこれを行う必要があります)、スレッドプールのサイズを増減して、重要なパフォーマンスメトリックを最適化できます。

3
Ralf H