web-dev-qa-db-ja.com

糸と繊維の違いは何ですか?

糸と繊維の違いは何ですか? Rubyの繊維について聞いたことがあり、他の言語で利用できると聞いたことがあります。スレッドと繊維の違いを簡単な言葉で誰かに説明できますか。

163
tatsuhirosatou

最も単純な用語では、スレッドは一般にプリエンプティブと見なされます(ただし、オペレーティングシステムによっては常に正しいとは限りません)が、ファイバーは軽量の協調スレッドと見なされます。どちらもアプリケーションの個別の実行パスです。

スレッドの場合:現在の実行パスはいつでも中断またはプリエンプトされる可能性があります(注:このステートメントは一般化であり、OS /スレッドパッケージなどによっては常に当てはまるとは限りません)。つまり、スレッドの場合、データのチャンクの更新中に1つのスレッドが停止し、データの整合性が不良または不完全な状態のままになる可能性があるため、データの整合性は大きな問題です。これは、同時に複数のスレッドを実行し、データアクセスを保護するために開発者に任せることで、オペレーティングシステムが複数のCPUとCPUコアを利用できることも意味します。

ファイバーの場合:現在の実行パスは、ファイバーが実行を譲るときにのみ中断されます(上記と同じ注意)。つまり、ファイバーは常に明確に定義された場所で開始および停止するため、データの整合性はそれほど問題になりません。また、ファイバーはユーザー空間で管理されることが多いため、高価なコンテキストスイッチやCPU状態の変更を行う必要がなく、ファイバー間の変更が非常に効率的になります。一方、2本のファイバーをまったく同時に実行することはできないため、ファイバーのみを使用するだけでは、複数のCPUまたは複数のCPUコアを利用できません。

144
Jason Coco

スレッドはpreemptiveスケジューリングを使用しますが、ファイバーはcooperativeスケジューリングを使用します。

スレッドを使用すると、制御フローがいつでも中断され、別のスレッドが引き継ぐことができます。複数のプロセッサを使用すると、複数のスレッドをすべて同時に実行できます(simultaneousマルチスレッド、またはSMT)。その結果、同時データアクセスにvery注意し、ミューテックス、セマフォ、条件変数などでデータを保護する必要があります。多くの場合、正しく実行するのは非常に難しいです。

ファイバーの場合、制御は、ユーザーが指示した場合にのみ切り替わります。通常、yield()などの名前の関数呼び出しを使用します。これにより、データ構造またはミューテックスの原子性を心配する必要がないため、同時データアクセスが容易になります。譲らない限り、preemptedになり、作業中のデータを別のファイバーが読み取ったり変更しようとしたりする危険はありません。ただし、結果として、ファイバーが無限ループに入った場合、他のファイバーは実行できません。

糸と繊維を混ぜて使用することもできます。これにより、両方が直面する問題が発生します。推奨しませんが、慎重に行うと正しいことになる場合があります。

52
Adam Rosenfield

Win32では、ファイバーはユーザー管理のスレッドの一種です。ファイバーには独自のスタックや命令ポインターなどがありますが、ファイバーはOSによってスケジュールされていません。SwitchToFiberを明示的に呼び出す必要があります。対照的に、スレッドは、オペレーティングシステムによってプリエンプティブにスケジュールされます。大まかに言って、ファイバーは、真のOSスレッドではなく、アプリケーション/ランタイムレベルで管理されるスレッドです。

その結果、ファイバーは安価になり、アプリケーションはスケジューリングをより細かく制御できるようになります。これは、アプリが多数の同時タスクを作成する場合、および/または実行時に厳密に最適化する場合に重要です。たとえば、データベースサーバーは、スレッドではなくファイバーの使用を選択する場合があります。

(同じ用語には他の用法があるかもしれません;述べたように、これはWin32の定義です。)

42
itowlson

最初に、この説明 プロセスとスレッドの違い を背景資料として読むことをお勧めします。

それを読んだら、それはかなり簡単です。スレッドは、カーネル、ユーザー空間のいずれかで実装できますが、2つを混在させることもできます。ファイバーは、基本的にユーザー空間に実装されるスレッドです。

  • 通常、スレッドと呼ばれるものは、カーネルに実装された実行スレッド、つまりカーネルスレッドです。カーネルスレッドのスケジューリングはカーネルによって排他的に処理されますが、カーネルスレッドは必要に応じてスリープすることでCPUを自発的に解放できます。カーネルスレッドには、ブロッキングI/Oを使用して、スケジューリングをカーネルに任せることができるという利点があります。主な欠点は、カーネルへのトラップを必要とするため、スレッドの切り替えが比較的遅いことです。
  • ファイバーは、単一プロセスの下で1つ以上のカーネルスレッドによってユーザー空間でスケジューリングが処理されるユーザー空間スレッドです。これにより、ファイバーの切り替えが非常に高速になります。単一のカーネルスレッドのコンテキストで共有データの特定のセットにアクセスするすべてのファイバーをグループ化し、それらのスケジューリングを単一のカーネルスレッドで処理する場合、ファイバーは事実上シリアルで実行され、完全なスケジューリングを制御します。関連するファイバーを単一のカーネルスレッドの下にグループ化することは重要です。それらが実行されているカーネルスレッドは、カーネルによって横取りされる可能性があるためです。この点は、他の多くの回答では明らかにされていません。また、ファイバーでブロッキングI/Oを使用する場合、カーネルスレッド全体は、そのカーネルスレッドの一部であるすべてのファイバーを含むブロックの一部です。

最新のオペレーティングシステムのセクション11.4「Windows Vistaのプロセスとスレッド」でTanenbaumはコメントしています。

ファイバーは協調的にスケジュールされますが、ファイバーをスケジュールする複数のスレッドがある場合、ファイバーが互いに干渉しないようにするために、多くの注意深い同期が必要です。スレッドとファイバー間の相互作用を単純化するには、それらを実行するプロセッサーと同数のスレッドのみを作成し、利用可能なプロセッサーの個別のセット、または1つのプロセッサーのみで各実行にスレッドをアフィニティ化すると便利です。次に、各スレッドはファイバーの特定のサブセットを実行し、スレッドとファイバーの間に1対多の関係を確立して、同期を簡素化します。それでも、繊維にはまだ多くの困難があります。ほとんどのWin32ライブラリはファイバーをまったく認識していないため、ファイバーをスレッドのように使用しようとするアプリケーションではさまざまな障害が発生します。カーネルはファイバーの知識がなく、ファイバーがカーネルに入ると、実行中のスレッドがブロックされ、カーネルはプロセッサー上の任意のスレッドをスケジュールし、他のファイバーを実行できないようにします。これらの理由により、ファイバーが提供する機能を明示的に必要とする他のシステムからコードを移植する場合を除き、ファイバーはほとんど使用されません。

35

Windows 7では、スレッドとファイバーに加えて、 ユーザーモードスケジューリング が導入されています。

ユーザーモードスケジューリング(UMS)は、アプリケーションが独自のスレッドをスケジュールするために使用できる軽量のメカニズムです。アプリケーションは、システムスケジューラを使用せずにユーザーモードでUMSスレッドを切り替え、UMSスレッドがカーネルでブロックされた場合にプロセッサの制御を取り戻すことができます。 UMSスレッドは、単一のスレッドのスレッドコンテキストを共有するのではなく、各UMSスレッドが独自のスレッドコンテキストを持つという点で、ファイバーとは異なります。ユーザーモードでスレッドを切り替える機能により、UMSはスレッドプールよりも効率的になり、システムコールをほとんど必要としない短期間の作業項目を多数管理できます。

スレッド、ファイバー、UMSの詳細については、 Dave Probert:Inside Windows 7-User Mode Scheduler(UMS) をご覧ください。

12
Grant Wagner

スレッドはOSによってスケジュールされます(プリエンプティブ)。スレッドはOSによっていつでも停止または再開できますが、ファイバーは多かれ少なかれそれ自体を管理(協調)し、互いに譲歩します。つまり、プログラマーは、繊維がいつ処理を行い、その処理が別の繊維に切り替わるかを制御します。

7
Arnold Spence

スレッドはもともと軽量プロセスとして作成されました。同様に、ファイバーは軽量のスレッドであり、制御を譲り渡すことにより、ファイバー自体に(単純に)依存して相互にスケジューリングします。

次のステップは、命令を実行するたびに信号を送信しなければならないストランドになると思います(私の5歳の息子とは違います:-)。昔(および一部の組み込みプラットフォームでも)、すべてのスレッドはファイバーであり、プリエンプションはなく、適切に動作するようにスレッドを記述する必要がありました。

7
paxdiablo

スレッドは通常、カーネルに依存してスレッドを中断するため、スレッドまたは別のスレッドを実行できます(プリエンプティブマルチタスクとして知られています)。他の繊維が走ることができます。

私がおそらくしたよりもそれを説明しているいくつかの有用なリンクは次のとおりです。

6
Mike Lowen

Win32ファイバーの定義は、実際にはSun Microsystemsで確立された「グリーンスレッド」の定義です。ある種のスレッド、つまりユーザーコード/スレッドライブラリ制御下のユーザー空間で実行されるスレッドでファイバーという用語を無駄にする必要はありません。

引数を明確にするには、次のコメントを見てください。

  • ハイパースレッディングを使用すると、マルチコアCPUは複数のスレッドを受け入れて、各コアに1つずつ分散できます。
  • スーパースカラーパイプラインCPUは、実行のために1つのスレッドを受け入れ、命令レベル並列処理(ILP)を使用してスレッドをより高速に実行します。 1つのスレッドが、並列パイプラインで実行されている並列ファイバーに分割されていると仮定できます。
  • SMT CPUは、複数のスレッドを受け入れ、それらを複数のパイプラインで並列実行するための命令ファイバーにブレーキをかけ、パイプラインをより効率的に使用できます。

プロセスはスレッドで構成され、スレッドはファイバーで構成されていると想定する必要があります。そのロジックを念頭に置いて、他の種類のスレッドにファイバーを使用するのは間違っています。

3
billmic