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


30

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

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

回答:


33

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

プロセス/スレッドです

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

これら3つのリソースはすべて有限であり、いずれもシステムのパフォーマンスを制限できます。特定の状況がどれを消費しているのかを確認する必要があります(2つまたは3つ)。

およびを使用ntopしてiostatvmstat何が起こっているかを診断できます。


8
ハードウェアも重要です。物理、仮想、コアの数、コアのタイプ、L1 / L2 / L3キャッシュなど
EightBitTony

46

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

1〜3人の人がいる場合、廊下スペースの使用を逃しています。5人以上の人がいる場合、それらの人の少なくとも1人は基本的に他の人の後ろで常にキューに入れられています。より多くの人を追加すると、廊下が詰まるだけで、活動性は加速しません。

したがって、待ち行列を発生させることなく、できるだけ多くの人を収容したいと考えています。 キューイング(またはボトルネック)がある理由は、slmの回答の質問に依存します。


1
あなたの例は誤解を招くものです。「4人を並べて配置できる廊下があり、あなた他の人がさまざまなタスクに使用します。廊下を通過できる人を決定する審判がいます。すると、最も効率的な人数は4人よりも多く、一部の人数よりも少なくなります。そこでは、人々がキューを開始します[高度なコンテキスト依存]。」通常、CPUの数よりも多くのスレッドを使用すると、正確に 4つのスレッドを使用するよりもパフォーマンスが向上します。CPUを使用しているのがあなただけなら、それ4が最適な数字です。
バクリウ

7
素晴らしい例、+ 1。バクリウ、その限られた共有リソースの問題を示す例。スレッドの最適な数を見つける方法ではなく、問題を説明しています。
バナンイン

1
スレッドには、独自のタイプのコンテキストスイッチングが引き続き行われることを覚えておくと便利です。スレッドの数を増やしても、パフォーマンス容量は増加しませんが(指摘したとおり)、カーネルの処理量を増やすことでCPU時間を浪費します。基本的に、スレッド化のリターンは減少し、多すぎるとパフォーマンスが逆行します。
ブラチリー

9
すべての問題は、さまざまなレベルの複雑さで説明できます。問題の近似を提示しましたが、これは基本を説明するのに役立つと思います。もちろん、より洗練された、より詳細なものにすることができますが、詳細にすればするほど、問題の紹介としては役に立たなくなります。
EightBitTony

追加するだけで、最適なスレッド数の計算に多くの時間を費やす代わりに、簡単に変更できるようにコーディングするだけです。このような大規模なマージを完了するには、多数のテスト実行(ほとんどの場合、データの小さなサブセット)が必要です。パフォーマンスが大幅に低下するか、他のシステムアクティビティへの影響が受け入れられなくなるまで、スレッドの数を増やします。
DocSalvager

20

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

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


これは、問題になっている情報の量を考えると一般的な答えになるはずです。他の答えのような本格的な論文や哲学は必要ありません
アッラージャネ

9

他の人が指摘しているように(slm answerEightBitTony answer)、これは複雑な質問であり、あなたがをしたか、どのようにそれを行う説明していないためです。

しかし、より多くのスレッドを確実にスローすると、事態が悪化する可能性があります。

並列コンピューティングの分野には、適用できる(またはできない、しかし、あなたの問題の詳細を記述しないなど)アムダールの法則があり、このクラスの問題に関する一般的な洞察を与えることができます。

アムダールの法則の要点は、どのプログラム(どのアルゴリズムでも)には常に並行して実行できない割合(順次部分)と、並行して実行できる別の割合(並行部分)があることです[明らかにこれらの2つの部分の合計は100%です。

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

ウィキペディアからの画像ウィキペディアの画像)

アムダールの法則は、プログラムの並列部分(75%など)ごとに、より多くのプロセッサを使用して作業を行う場合でも、これまで(たとえば最大4倍)だけ実行を高速化できると予測しています。

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

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

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

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

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


これは選択された答えでなければなりません。
エオニル

6

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

あなたの場合、50個のスレッドがある場合、10個のスレッドを実行するだけと比較すると、多くのコンテキストの切り替えが発生します。

コンテキストの切り替えのために導入されたこの時間のオーバーヘッドは、プログラムの実行を遅くするものです


スレッドが何なのかわからないので、これは推測のようです。はい、コンテキストスイッチングはオーバーヘッドを追加しますが、スレッドが何らかのデータ分析を行っている場合、問題はキャッシュの問題である可能性があります(つまり、スレッドを切り替えるたびにフラッシュする必要があるため、キャッシュを使用できない)。
EightBitTony

スレッドコンテキストスイッチング自体は、膨大な数のコンテキストスイッチングを処理しない限り、パフォーマンスに大きな影響を与えることはないでしょう。50個のスレッドは高いですが、極端ではありません(私のボックスでは、ps ax | wc -l225プロセスを報告し、決して負荷が高いわけではありません)。私は@EightBitTonyの推測にしたがいます。キャッシュの無効化は、キャッシュをフラッシュするたびに、CPUがRAMからのコードとデータを何年も待つ必要があるため、大きな問題になる可能性があります。
CVn

3

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

「なぜこれが起こるのですか?」簡単に答えられます。あなたが持っている想像して2つのスイミングプール、完全な1と1つの空を。すべての水を一方から他方に移動し、4つのバケツを持ちます。最も効率的な人数は4です。

1〜3人の人がいるならば、いくつかのバケツを使うのを逃しています。5人以上の人がいる場合、そのうちの少なくとも1人がバケツを待って立ち往生しています。より多くの人を追加しても、アクティビティはスピードアップしません。

そのため、同時にいくつかの作業(バケットを使用)を実行できる数の人が必要です

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

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

数人の人が示唆しているように、I / Oの場合、制限リソースは、キューイング可能なI / O操作の数になります。これは、ハードウェアとカーネルの要因全体に依存しますが、コア。ここでは、実行バインドコードと比較して非常に高価なコンテキストスイッチは、I / Oバインドコードと比較してかなり安価です。残念ながら、これをバケットで正当化しようとすると、隠metaは完全に制御不能になると思います。

ことを注意最適な I / Oバウンドコードで動作が一般的である、まだパイプライン/コア/ CPUあたり最大1つのスレッドで持っています。ただし、非同期または同期/非ブロッキングI / Oコードを作成する必要があり、比較的小さなパフォーマンスの改善が常に余分な複雑さを正当化するとは限りません。


PS。元の廊下のメタファーに関する私の問題は、4つの人の列があり、2つの列がゴミを運び、2つの列がより多くを集めるために戻ることができることを強く示唆していることです。そして、あなたは廊下とほぼ限り、各キューを作ることができ、そして追加の人がやったアルゴリズムのスピードアップを(あなたは、基本的には、コンベヤベルトに全体の廊下を回しました)。

実際、このシナリオは、TCPネットワーキングでの待ち時間とウィンドウサイズの関係に関する標準的な説明と非常によく似ているため、私は飛び出しました。


それは比phorではなく、システムを簡単に視覚化できる方法でシステムを説明するために設計された近似値です。そのため、次のレベルの詳細を知っているが、初心者には実際にその詳細レベルが実際に必要でないことに気付かない人は、常に「ごみ」になります。PhDレベルから始めて粒子物理学を学ぶ人はいません。以前のすべてのものは近似値であり、徐々にあなたを導き、あなたが行くにつれてそれを洗練していきます。それは「間違った」ものではなく、単に全体像ではありません。
EightBitTony

誰がどのスピーチの数字を使用したかについて混乱することはありません。それは悪い例えではありません。すべての類推には限界があり、それを超えると説明すべきものとは異なり、有用ではなくなる。これは、オリジナルが別のシナリオを非常に強く思い出させたため、そしてこのバージョンが(願わくば)改善された予測性のためにこれ以上複雑になるとは思わないからです。
役に立たない

0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.