web-dev-qa-db-ja.com

マルチスレッドとマルチプロセッシング

私はこの種のプログラミングは初めてなので、あなたの視点が必要です。

アプリケーションを構築する必要がありますが、十分な速度で計算することはできません。すでにインテルTBBを試しましたが、簡単に使用できますが、他のライブラリを使用したことはありません。

マルチプロセッサプログラミングでは、マルチスレッド用のOpenMPとBoostについて読んでいますが、それらの長所と短所はわかりません。

C++では、マルチスレッドプログラミングと比較してマルチスレッドプログラミングが有利なのはいつですか?彼らと一緒に設計されたアプリケーションを構築するとき、彼らの長所と短所は何ですか?最後に、どのライブラリを使用するのが最適ですか?

30
Nazka

マルチスレッドとは、まさに複数のスレッドを実行することを意味します。これは、ユニプロセッサシステムまたはマルチプロセッサシステムで実行できます。

シングルプロセッサシステムでは、複数のスレッドを実行しているときに、コンピューターが複数のことを同時に行っている(つまり、マルチタスク)の実際の観察は幻想です。これは、実際にソフトウェアスケジューラーが存在するためです単一のCPUでタイムスライスを実行します。そのため、常に1つのタスクのみが発生しますが、スケジューラはタスク間を十分に高速で切り替えているため、同じCPUリソースを求めて競合する複数のプロセス、スレッドなどがあることに気付くことはありません。

マルチプロセッサシステムでは、タイムスライスの必要性が減少します。最新のOSでは、2つ以上のプロセッサをめぐって競合する数百のスレッドが存在する可能性があり、通常、スレッドの数と利用可能な処理コアの数が1対1の関係になることはないため、タイムスライス効果は依然として存在します。そのため、ある時点で、スレッドを停止し、2つのスレッドが共有しているCPUで別のスレッドを開始する必要があります。これもOSのスケジューラーによって処理されます。つまり、マルチプロセッサシステムでは、canユニプロセッサシステムとは異なり、同時に2つのことが発生します。

最終的に、2つ以上のタスクを非同期で実行したい場合は常にマルチスレッドが必要になるという意味で、2つのパラダイムはやや直交していますが、タイムスライシングのため、必ずしもマルチプロセッサシステムが必要なわけではありませんそれ。複数のスレッドを実行しようとしていて、高度に並列化されたタスクを実行している場合(つまり、積分を解決しようとしている場合)、はい、問題でスローできるコアが多いほど良いです。スレッドとプロセッシングコアの間に1対1の関係は必ずしも必要ではありませんが、同時に、多くのスレッドをスピンオフして、アイドルスレッドが大量に発生するのを待たなければならないため、使用可能なCPUコアの1つでスケジュールされます。一方、並列タスクにシーケンシャルコンポーネントが必要な場合、つまり、スレッドが続行する前に別のスレッドからの結果を待機している場合、何らかのタイプのバリアまたは同期メソッドでより多くのスレッドを実行できる可能性があります。アイドル状態である必要があるスレッドはCPU時間を使用してスピンオフしておらず、実行する必要があるスレッドのみがCPUリソースを奪い合っていることを確認します。

54
Jason

@Jasonの優れた回答に追加すべき重要な点がいくつかあります。

第一に、マルチスレッドは単一のプロセッサ上でも常に幻想とは限りません-プロセッサに関係しない操作があります。これらは主にディスク、ネットワーク、端末などのI/Oです。このような操作の基本的な形式はblockingまたはsynchronous。つまり、プログラムは操作が完了するまで待機してから続行します。待機中に、CPUは別のプロセス/スレッドに切り替えられます。

その間にできることがあれば(たとえば、ユーザー入力を待っている間のバックグラウンド計算、別のリクエストの処理など)、基本的に2つのオプションがあります。

  • 非同期I/Oを使用するノンブロッキングI/Oを呼び出してcallback function、「完了したらこの関数を呼び出す」と伝えます。呼び出しはすぐに戻り、I/O操作はバックグラウンドで続行されます。あなたは他のものに進みます。

  • マルチスレッドを使用:タスクの種類ごとに専用のスレッドがあります。一方がブロッキングI/O呼び出しを待つ間、もう一方は継続します。

どちらのアプローチも難しいプログラミングパラダイムであり、それぞれに長所と短所があります。

  • 非同期I/Oでは、プログラムのロジックのロジックはそれほど明確ではなく、追跡およびデバッグが困難です。ただし、thread-safetyの問題は避けます。
  • スレッドの場合、課題は thread-safe プログラムを書くことです。スレッドセーフティフォールトは、再現が非常に難しい厄介なバグです。ロックを使いすぎると、実際にはパフォーマンスが向上する代わりに低下する可能性があります。

(マルチプロセッシングに来る)

マルチスレッドは、Windowsではプロセスの操作(プロセスの作成、コンテキストの切り替えなど)が非常に重いため、Windowsでは一般的になりました(少なくともWin2Kで作業した場合はそうでした)。

Linux/Unixでは、プロセスははるかに軽量です。また、Linuxの(AFAIK)スレッドは、実際には一種のプロセスとして内部的に実装されているため、スレッドとプロセスのコンテキスト切り替えにはメリットがありません。ただし、何らかの形式のIPC(プロセス間通信)を共有メモリ、パイプ、メッセージキューなどとして使用する必要があります。

より詳細な注意事項については、「スレッドは悪」と宣言されている SQLite FAQ をご覧ください! :)

21
davka

最初の質問に答えるために:最良のアプローチは、それでも十分な利益が得られなくなるまで、コードでマルチスレッド技術を使用することです。 OSが使用可能な場合、複数のプロセッサへの委任を処理すると仮定します。

複数のプロセッサを使用しても、マルチスレッドでは不十分な問題に実際に取り組んでいる場合(または、複数のプロセッサを使用していないOSで実行している場合)、より多くの電力を得る方法の発見を心配することができます。これは、ネットワークを介して他のマシンにプロセスを生成することを意味する場合があります。

TBBを使用したことはありませんが、IPPを使用し、効率的で適切に設計されていることがわかりました。 Boostはポータブルです。

4
Mike C

フローベースプログラミング( http://www.jpaulmorrison.com/fbp )パラダイムは、アプリケーション開発に対する当然のマルチプログラミング/マルチプロセッシングアプローチであることを言及したかっただけです。高レベルから低レベルまで一貫したアプリケーションビューを提供します。 JavaおよびC#実装は、マシン上のすべてのプロセッサを利用しますが、古いC++実装は1つのプロセッサのみを使用します。ただし、BOOST(またはpthread、I私はそれをファイバーを使用するように変換し始めていましたが、このルートを継続することに意味があるかどうかはわかりません。ところでJavaとC#の実装は、ソケットを使用して相互通信することさえできます。

0
Paul Morrison