web-dev-qa-db-ja.com

IO操作を含まないタスクにはマルチスレッドを使用する必要がありますか?

私はOSに関する本を読んでいて、異なる用語の間で混乱しました。ここで私の疑問が解消されることを願っています。これらの質問は一部のエキスパートにとっては非常に基本的なものかもしれませんが、このプラットフォームはそのような説明に最も適していると思います。

プロセスはCPUによって実行され、この操作全体はOSによって管理されます。シングルコアCPUの場合、常に1つのプロセスのみが実行されます。 CPUはプロセスの状態をプロセスコントロールブロックに保存し、待機していた別のプロセスの実行を開始します。この切り替えは非常に高速で、すべてのプロセスが同時に実行されているように感じます。

プロセス内でさまざまなスレッドの必要性がプロセスをよりきめ細かく制御できるように感じられました。つまり、I/Oバインド操作のためにプロセスが待機している場合、このプロセスがCPUによって選択されても、何も実行されません。

したがって、1つのプロセスで複数のスレッドが実行されている場合、1つのスレッドがI/Oアクティビティを処理すると、このプロセスがCPUによって選択されていれば、他のスレッドが実際の計算を実行できます。

ここに私の質問があります:マルチスレッドは、タスクにI/Oアクティビティが含まれる場合にのみ有効ですか?マルチスレッドがマルチプロセッシングよりも好ましいのはなぜですか? (スレッドが同じメモリ空間を共有するためでしょうか?)

マルチコアプロセッサがマルチスレッドに適している理由(マルチスレッディングを使用しなくても、それらは優れていると思います。なぜマルチスレッディングという名前でそれほど興奮するのでしょうか。)とにかく、異なるプロセスのスレッドは同じメモリを共有しないため、異なるコアの異なるプロセスで実行されている2つのスレッドは、異なるプロセスを実行しているようです。それはそれらが平行であり、実際の平行であり、疑似平行ではないということです。

6
AKS

完全にCPUにバインドされたプロセスでさえスレッドを使用する主な理由の1つは、何らかのUIを介して対話または進行状況の出力を更新できるようにすることです。インタラクションを許可せずにフォアグラウンドで計算を実行する方が効率的ですが、タスクの切り替えとUIイベントの処理のわずかなコストは、通常、ユーザーに無期限にプロセスを待機させるというペナルティを上回ります。

1つのコアで複数のスレッドを実行する方が効率的であるもう1つのケースは、マルチステージプロセスに、後のステージで処理される多くの一時的な結果を生成する1つのステージが含まれる場合です。これらのステージを連続して実行すると、使用可能なメモリを使い果たす可能性があります。それらを並行して実行すると、第2ステージで結果を処理するときにメモリを解放できます。

最後に、アーキテクチャにキャッシュを追加すると、メモリへのアクセス中にキャッシュミスが発生すると、スレッドがアイドルになることがよくあります。これにより、別のスレッドがアクティブになり、いくつかの作業を行う時間を確保できます。

マルチプロセッシングに対するマルチスレッドの主な利点は次のとおりです。

  • 共有メモリ
  • コンテキスト切り替えのオーバーヘッドが少ない
  • より簡単な抽象化

最新のオペレーティングシステムのほとんどは、プロセス間でメモリを共有する方法も提供しています。それでも、OSまたは仮想マシンがスレッドを複数のプロセッサ間でシフトできるようにすることは、利用可能な場合に非常に魅力的です。たとえば、マルチスレッドのJavaプログラムをシングルコアマシンからマルチコアのマシンに移動すると、JVMはそれらの他のコアを自動的に利用します。

3
David Harkness

あなたの質問の下にいくつかの誤解があるようです。

  • 各CPUが独自の専用メモリを備えたアーキテクチャを持つことは可能ですが、これはマルチコアプロセッサには当てはまりません。スーパーコンピューターやコンピューティングクラスターで作業しているときに、このようなアーキテクチャに遭遇する場合があります。
    マルチコアプロセッサでは、各コアに独自のキャッシュがありますが、メモリの大部分(すべてのRAM)はコア間で共有されます。つまり、同じプロセス(アプリケーション)の2つのスレッドが、異なるコアで同時に実行される可能性があります。
  • 実行するタスクを選択するのはCPUではなく、各CPUで実行するタスクを選択するのはOS(のスケジューラ)です。この選択では、タスクがある程度進行できることがOSで認識されているタスクのみが考慮されます。何かを待つタスク(IO操作の完了、ロックの解放など)は、条件が満たされていることをOSが認識するまで、スケジューリングの対象とは見なされません。

あなたの質問に答えるには:

  1. 通常、長時間実行される計算や潜在的にI/Oをブロックしないユーザーインタラクション用に別のスレッドを用意することをお勧めします。これにより、アプリケーションの認識される応答性が向上します。
    また、計算を実行する複数のスレッドを用意すると、それらが異なるコアで実行される可能性があり(複数のコアが使用可能な場合)、アプリケーションの設計を単純化できるため、さらに利点があります。 CPUが1つしかない場合。
  2. スレッド間で同じメモリを共有するため、スレッド間通信の方がプロセス間通信よりも理解/指定がしやすいため、マルチスレッド化はマルチプロセスよりも好まれることがよくあります。また、OSのスレッド実装によっては、スレッド間のタスク切り替えの方がプロセス間のタスク切り替えよりも効率的です。

I/O以外にもスレッドを使い始めた理由はいくつかあります。その理由の1つは、シングルスレッドの世界に慣れている方がプログラミングが簡単だと思われることです。昔は、単一のプロセスで大量のI/Oを処理することは、デバッグと理解が困難な非常に複雑な状態マシンを作成することを意味していました。また、このようなステートマシンを実行すると、計算が長くなるとアプリケーションが応答しなくなるため、計算を細かく分割する必要があります。古いNetscape Navigatorはそのように行われました。

通常、スレッドごとに異なるコアを使用できるため、I/Oが少ないCPUにバインドされた操作がある場合、それらの操作はアプリケーションの残りの部分をブロックせずに別のコアで実行できます。それはあなたが言ったことの逆なので、スレッドについて考えているのは、一部の場所ではグリーンスレッドと呼ばれるものです。つまり、オペレーティングシステムによってスケジュールされていないスレッドです。コードの一部は、制御を放棄するまで、つまりI/Oまたは制御を実行するまで実行されます。

現在、人々がマルチプロセッシングよりもマルチスレッディングを好む理由はいくつかあります。プロセスは通常メモリを共有しないため、多くのプログラミングスタイルは不可能です。メモリ内のデータ構造を更新する代わりに、別のプロセスにメッセージを送信する必要があり、他のプロセスはそれを解釈する必要があります。これが今日の多くの言語で機能し、多くの言語に適していますが、プログラミングスタイルは異なります。別の理由は、プロセスは通常スレッドよりも重く、リソースを大量に消費するためです。アプリケーションに数百のスレッドを含めることはできますが、通常は数百のプロセスを含めることはできません。

0
Andre Manoel

並列処理を理解することになると(この用語を一般的な用語として使用します)、基本から始めるのが最善です。最初はゆっくりとシンプルにしてください。

スレッドとプロセスはほとんど同じだと私は理解していますが、スレッドは軽量のワークシステムであり、プロセスは重量があります。これらは、これらの作業手配をサポートするために生成する必要があるシステム作業の量を示すために使用される用語です。並列処理はコンピュータに余分な作業を引き起こすため、これは重要な問題です。タスクが非常に多くのスレッドを生成する場合、同じ作業を行うために同じ数のプロセスを生成する必要がある場合よりも効率的です。

可能な限り広い意味でI/Oを理解するようにしてください。これは、ユーザー入力、または大容量記憶装置(ディスク)へのI/Oだけではありません。 CPUから見ると、メインメモリからの読み取りはI/Oです。キャッシュ読み取りもI/Oであり、最速のレベル1キャッシュであってもです。並列処理により、1つのスレッド(またはプロセス)がI/Oを待機している場合でも、他の非ブロックスレッドが実行を継続できるため、生産的な作業を続行できます。

また、スポーンしたスレッドの実行順序がわかっている、または制御されていると思って立ち往生しないでください。並列タスクの同期を強制できますが、問題のロジックで必要な場合にのみ実行してください。同期は、プログラムの実行速度を遅くし、厳密に必要でない限り悪いです。

最新のCPUは内部的には複雑な野獣であり、アセンブリ言語ステートメントでさえもマイクロ命令に分解されます。

複数のCPUとCPUを利用するコアのすべての話は、単なるハードウェア実装のものです。多くの場合、コアベースではない単一のCPUでも、並列ソフトウェアを非常に効果的に使用できます。 OSとアプリケーションのサポートが必要なだけです。

プロセッサー能力の大まかな階層(命令実行能力の昇順)は次のとおりです。

  1. シングルCPU、マルチコアなし
  2. マルチCPU、マルチコアなし
  3. シングルCPU、マルチコア
  4. マルチCPU、マルチコア

どうして?マルチコアCPUは、タスクを別のCPUに送信するよりもはるかに速く内部コアにタスクをルーティングできます。また、マルチコアCPUは、シングルコアCPUよりも定期的にキャッシュレベルを共有します。これにより、より高速なデータ共有も可能になります。

私が見た大雑把な指標は、単一のCPU内で1つのコアから別のコアにタスクを送信する方が、そのタスクをオフチップで別のCPUに送信する必要がある場合よりも約10倍速いということです。

スーパーコンピュータのように日常的に使用されているシェアードナッシングアーキテクチャは、これをさらに高いレベルで抽象化することにも注意してください。次に、複数のコンピュータ全体が連携して1つのユニットとして機能します。命令処理能力は上がりますが、プロセス間通信(IPC)のオーバーヘッドも上がります。これは、電力の増加に直接類似していますアテンダントIPCオーバーヘッドは、複数のシングルコアCPUと1つのマルチコアCPUの間にあります。単一のオペレーティングシステム。

並列処理をプログラミングするための一般的なガイドラインを次に示します。

  • ロジックが許す限り、できるだけ多くの並列タスクを実装します。
  • 現在のCPU設計と関連付けるためにスポーンするサブタスクの数を調整しようとしないでください。
  • cPUの命令処理能力を推測することは避けてください。
  • 可能な限りプロセスの同期を避けます。

実際、できる限り現在のハードウェアに合わせて設計しないことは、良い設計パターンです。ソフトウェアの寿命は非常に長く、ハードウェアの寿命は比較的短く、固定されています。したがって、ハードウェアよりもソフトウェアに(時間を費やすことにより)賭けます。ハードウェアが変わるので、それを当てにすることができます。

0
Brian Too