web-dev-qa-db-ja.com

より多くのスレッドを使用すると、少ないスレッドを使用するよりも遅くなる理由

8スレッドを使用してプログラムXを実行しようとしましたが、n分で終了しました。
50スレッドを使用して同じプログラムを実行しようとしましたが、n * 10分で終了しました。

なぜこれが発生し、使用できるスレッドの最適な数を取得するにはどうすればよいですか?

30
PoGibas

これはあなたが尋ねている複雑な質問です。スレッドの性質について詳しく知らないと、言うのは困難です。システムパフォーマンスを診断する際に考慮すべきいくつかの事項:

プロセス/スレッド

  • CPUバウンド(大量のCPUリソースが必要)
  • メモリ制限(RAMリソース)が大量に必要)
  • I/Oバウンド(ネットワークおよび/またはハードドライブリソース)

これら3つのリソースはすべて有限であり、システムのパフォーマンスを制限する可能性があります。特定の状況でどれが消費されているか(一緒に2または3になる可能性がある)を調べる必要があります。

ntopiostat、およびvmstatを使用して、何が起こっているのかを診断できます。

33
slm

「なぜこれが起こるのですか?」答えるのは簡単です。 4人を並べて並べることができる廊下があるとします。あなたは一方の端にあるすべてのゴミをもう一方の端に移動したいと考えています。最も効率的な人数は4名です。

1〜3人いる場合は、廊下スペースを利用できません。 5人以上の人がいる場合、それらの人の少なくとも1人は、基本的に常に他の人の後ろにキューイングされています。ますます多くの人々を追加することは、廊下を詰まらせるだけで、活動をスピードアップしません。

そのため、キューに入れずに、できるだけ多くの人を収容したいと考えています。 理由キューイング(またはボトルネック)があるかどうかは、slmの回答の質問によって異なります。

46
EightBitTony

一般的な推奨事項は、n + 1スレッドで、nは使用可能なCPUコアの数です。これにより、1つのスレッドがディスクI/Oを待機している間、n個のスレッドがCPUを機能させることができます。スレッドが少ないと、CPUリソースを完全には利用できません(ある時点で、待機するI/Oが常にあります)。スレッドが多いと、スレッドがCPUリソースを争う原因になります。

スレッドは解放されませんが、コンテキストスイッチのようなオーバーヘッドが発生します。通常、スレッド間でデータを交換する必要がある場合は、さまざまなロックメカニズムが使用されます。これは、コードを実行する専用のCPUコアが実際にある場合にのみ、コストに見合う価値があります。シングルコアCPUでは、通常、単一のプロセス(個別のスレッドはありません)は、実行されるどのスレッドよりも高速です。スレッドは、魔法のようにCPUを高速化するのではなく、余分な作業を意味します。

20
frostschutz

他の人が指摘したように( slm answerEightBitTony answer )これは複雑な質問であり、whatスレッドが実行し、方法スレッドが実行します。

しかし、確実に多くのスレッドを投入すると、事態はさらに悪化する可能性があります。

並列計算の分野には アムダールの法則 があり、適用可能である(または適用できないが、問題の詳細を記述しないので....)あり、一般的な洞察を得ることができます。このクラスの問題。

アムダールの法則の要点は、どのプログラムでも(どのアルゴリズムでも)常にできないパーセンテージがある並列実行できない(順次部分)そして、ができる別の割合があります並列に実行する(並列部分)[明らかにこれらの2つの部分が追加されます100%まで]。

この部分は、実行時間の割合として表すことができます。たとえば、厳密な順次操作に費やされる時間の25%があり、残りの75%の時間は、並行して実行できる操作に費やされます。

Image from Wikipedia (画像 Wikipedia

アムダールの法則は、プログラムの特定の並列部分(75%など)ごとに、処理を実行するために使用するプロセッサの数が増えても、これまで(最大で4倍)だけ実行を高速化できると予測しています。

経験則として、並列実行で変換できないプログラムが多いほど、より多くの実行ユニット(プロセッサ)を使用して取得できなくなります。

物理プロセッサではなくスレッドを使用している場合、状況はこれよりもさらに悪化する可能性があります。スレッドを処理できることを覚えておいてください(実装や利用可能なハードウェアに応じて、CPU /コアなど)sharing同じ物理プロセッサ/コア(マルチタスクの一種です) 、別の答えで指摘されているように)。

この理論上の予測(CPU時間について)では、他の実用的なボトルネックは考慮されていません。

  1. 制限されたI/O速度(ハードディスクおよびネットワークの「速度」)
  2. メモリサイズの制限
  3. その他

これは、実際のアプリケーションでは簡単に制限要因になります。

10
DavAlPi

ここでの犯人は「CONTEXT SWITCHING」です。現在のスレッドの状態を保存して、別のスレッドの実行を開始するプロセスです。複数のスレッドに同じ優先順位が与えられている場合、実行が完了するまでスレッドを切り替える必要があります。

あなたのケースでは、50のスレッドがある場合、10のスレッドを実行するだけの場合と比較して、多くのコンテキストの切り替えが行われます。

コンテキストの切り替えが原因でこの時間オーバーヘッドが発生し、プログラムの実行が遅くなります

6
x-treme

EightBitTonyのメタファーを修正するには:

「なぜこれが起こるのですか?」答えるのは簡単です。あなたが持っていると想像してください2つのプール、1つは満杯でもう1つは空です。すべての水を1つの水から別の水に移動し、4つのバケツを用意します。最も効率的な人数は4名です。

1〜3人の場合、一部のバケットを使用できません。 5人以上の人がいる場合、そのうちの少なくとも1人がスタックしますバケットを待っています。ますます多くの人々を追加することは...活動をスピードアップしません。

つまり、同時にいくつかの作業を行うことができます(バケットを使用)です。

ここでの人はスレッドであり、バケットは実行リソースのボトルネックを表します。スレッドを追加しても、何もできない場合は役に立ちません。さらに、バケットを1人から別の人に渡すは、通常、バケットを同じ距離だけ運ぶ一人よりも遅いことを強調する必要があります。つまり、コアを順番に実行する2つのスレッドは、通常、2倍の長さで実行される単一のスレッドよりも少ない作業を実行します。これは、2つのスレッドを切り替えるために追加の作業が行われるためです。

制限する実行リソース(バケット)がCPU、コア、またはハイパースレッドの命令パイプラインのどちらであるかは、アーキテクチャのどの部分が制限要因であるかによって異なります。また、スレッドは完全に独立していると想定していることにも注意してください。これは、それらがnoデータを共有する場合にのみ該当します(キャッシュの衝突を回避します)。

数人が示唆したように、I/Oの制限リソースは、キューに入れられる有用なI/O操作の数である可能性があります。これは、ハードウェアのホスト全体とカーネル要素に依存する可能性がありますが、コア。ここでは、実行バインドコードに比べてコストがかかるコンテキストスイッチは、I/Oバインドコードに比べてかなり安価です。悲しいことに、これをバケツで正当化しようとすると、比喩は完全に制御できなくなると思います。

I/Oバウンドコードでのoptimal動作は通常stillであり、パイプライン/コア/ CPUごとに最大1つのスレッドを持つことに注意してください。ただし、非同期または同期/非ブロックのI/Oコードを作成する必要があり、比較的小さなパフォーマンスの向上だけで常に複雑さが増すわけではありません。


PS。元の廊下のメタファーに関する私の問題は、4つの列にゴミを持ち、2つの列にゴミを持ち、2つの列にゴミを集めることができることを強く示唆しています。次に、コリドーとほぼ同じ長さの各キューを作成し、人を追加するdidアルゴリズムを高速化できます(基本的に、コリドー全体をコンベヤーベルトに変えました)。

実際、このシナリオは、TCPネットワーキングのレイテンシとウィンドウサイズの関係についての標準的な説明と非常によく似ています。そのため、私が飛びつきました。

3
Useless

非常に簡単で理解しやすいです。 CPUがサポートするよりも多くのスレッドがある場合、実際にはシリアル化されており、並列化されていません。スレッドが多いほど、システムは遅くなります。あなたの結果は実際にはこの現象の証拠です。

0
Bruno Taboada