1. ホーム
  2. ルビー

[解決済み】rubyには本当のマルチスレッドがあるのか?

2022-03-30 18:47:21

質問

Rubyの協調スレッドについて知っています。 グリーンスレッド . 複数のCPUコアを処理に利用するために、私のアプリケーションで本物の "OS-level" スレッドを作成するにはどうしたらよいでしょうか?

どのように解決するのですか?

Jörg氏の2011年9月のコメントを更新しました。

を混同しているようです。 非常に ここで異なるもの:それは Ruby プログラミング言語と、ある特定のスレッドモデル。 Ruby プログラミング言語の特定の実装。これは 現在、約11種類のRubyの実装があります。 プログラミング言語 非常に 異なる独自のスレッド処理 モデルを使用します。

(残念ながら、この11の実装のうち、実際に実装されているのは2つだけです。 しかし、年末までには、その数は減少するでしょう。 は4つか5つに増えるでしょう)。( 更新情報 MRI、JRuby、YARV (Ruby 1.9用インタプリタ)、Rubinius、IronRuby) の5つになっています。

  1. 最初の実装は、実は名前がないんです。 を参照するのはかなり厄介で、本当に迷惑なことです。 混乱させる。これは最もよく"Ruby"と呼ばれますが、これはさらに紛らわしいものです。 名前がないことよりも、もっと厄介で紛らわしい。 Rubyの特徴を限りなく混同させることになる。 プログラミング言語と、特定のRuby実装。

    また、quot;MRI" ("Matz's Rubyの略)と呼ばれることもあります。 Implementation")、CRuby、MatzRubyなどがあります。

    MRIは、RubyスレッドをGreenスレッドとして インタープリター . 残念ながら、このスレッドは は並列にスケジュールすることができず、一度に1つのスレッドしか実行できません。 となります。

    ただし、C言語のスレッド(POSIXスレッドなど)は、いくつでも実行可能です。 はRubyスレッドと並列に動作するため、外部のCライブラリやMRI スレッドを作成するC言語拡張は、まだ実行することができます。 並列

  2. 2つ目の実装は YARV ("Yetの略) Another Ruby VM")と呼ばれています。 YARVは、RubyのスレッドをPOSIXまたは Windows NTスレッド しかし、グローバル・インタープリタ ロック(GIL)することで、1つのRubyスレッドしか実際に使用できないようにする。 をスケジュールすることができます。

    MRIと同様、C言語のスレッドも できる 実際にRuby Threadsと並行して動作しています。

    将来的にはGILの かもしれない 分解される をより細かくロックできるようになり、その結果、より多くの しかし、それはあまりにも遠い未来のことで、実際に並列に実行されるコードではありません。 もない 予定 まだです。

  3. JRuby Ruby のスレッドをネイティブスレッドとして実装しています。 , ここで、JVMの場合の"Native Threads"は、明らかに"JVMを意味します。 Threads"です。JRubyでは、それらに追加のロックは課されません。ですから これらのスレッドが実際に並列に実行できるかどうかは、以下の点に依存します。 JVMによっては、JVMスレッドをOSスレッドとして実装しているものもあれば をGreen Threadsとして使用します。(Sun/Oracleの主流のJVMは、JDK 1.3以降、OSスレッドのみを使用します)

  4. XRuby また Ruby のスレッドを JVM のスレッドとして実装する。 . 更新情報 : XRuby は終了しました。

  5. IronRuby Ruby のスレッドをネイティブスレッドとして実装しています。 , ここで、CLRの場合の "Native Threads" とは、明らかに CLRスレッドです。IronRubyはそれらに追加のロックをかけません。 CLRがサポートしている限り、並列に実行されるはずです。 ということです。

  6. Ruby.NET また Ruby のスレッドを CLR として実装しています。 スレッド . 更新してください。 Ruby.NETは死にました。

  7. ルビニウス は、Ruby スレッドを Green スレッドとして実装しています。 仮想マシンの中で . より正確には、Rubinius VM は、非常に軽量で非常に柔軟な と呼ばれる、並行処理/並列処理/非局所的なコントロールフロー構造です。 a "です。 タスク その他のすべての並行処理構成要素(ここではThreads)を含みます。 この議論だけでなく コンティニュエーション , アクター および など)は、Tasksを使って、純粋なRubyで実装されています。

    Rubiniusでは、スレッドを並列にスケジュールすることは(現在のところ)できません。 しかし、それを追加することはあまり問題ではありません。Rubiniusは すでに 複数のVMインスタンスを複数のPOSIXスレッドで同時に実行します。 並列 1つのRubiniusプロセス内で。スレッドは 実際にRubyで実装されているため、他のRubyと同じように オブジェクトをシリアライズし、別のVMに送ることができます。 POSIX スレッドです。(これはBEAMのモデルと同じです。 アーラン VM はSMP並行処理に使用しています。それはすでに に実装されています。 Rubiniusアクター .)

    更新情報 : この回答にあるRubiniusに関する情報はShotgun VMに関するもので、もう存在しないものです。新しいC++ VMは、複数のVMにまたがってスケジュールされたグリーンスレッド(つまりErlang/BEAMスタイル)を使用せず、CLRやMono、そしてほとんどすべてのJVMが採用しているような、複数のネイティブOSスレッドを持つ、より伝統的な単一VMモデルを使用します。

  8. MacRuby の上にYARVを移植することから始まりました。 Objective-CランタイムとCoreFoundation、Cocoaフレームワーク。それは は現在YARVから大きく乖離していますが、AFAIKでは現在 今も YARVと同じスレッディングモデルを共有する . 更新してください。 MacRubyはリンゴのガベージコレクタに依存していますが、これはMacOSXの後のバージョンで非推奨とされ、削除される予定です、MacRubyは不死身です。

  9. カーディナル の Ruby 実装です。 パロット 仮想マシン . ただし、スレッドはまだ実装されていない。 として実装されるでしょう。 パロット スレッド . 更新情報 : カーディナルは非常に不活発/死んでいるようです。

  10. MagLev の Ruby 実装です。 GemStone/S スモールトークVM . 私は、どのようなスレッドモデルであるかの情報を持っていません。 GemStone/S が使っているスレッドモデル、MagLev が使っているスレッドモデル、さらには はまだ実装されていません(おそらく)。

  11. HotRuby ない 完全なRubyの実装である を所有しています。これはYARVバイトコードVMの実装で JavaScriptです。HotRubyはスレッドをサポートしておらず(まだ?)、また、スレッドをサポートした場合 というのも、JavaScriptでは並列に動作させることができないからです。 は真の並列処理をサポートしていません。ActionScript しかし、HotRubyのバージョンは、ActionScriptは、実際に可能性があります。 は並列処理をサポートしています。 更新情報 : HotRubyは終了しました。

残念ながら、この11のRuby実装のうち、2つだけが 実際に生産可能な状態です。MRIとJRubyです。

つまり、本当の意味での並列スレッドが必要な場合は、現在のところJRubyを使うしかありません。 という選択肢しかありません。JRubyは実際に高速です。 MRIよりも安定しています。

そうでない場合、Ruby の古典的な解決策は、プロセスを使用することです。 スレッドの代わりに並列処理を行います。Rubyコアライブラリ には Process モジュール と共に Process.fork メソッド を使用すると、別のRubyをフォークオフするのが非常に簡単になります。 プロセスです。また、Ruby標準ライブラリには 分散ルビー (dRuby / dRb) このライブラリは、Ruby コードを複数のプロセスに分散させることができます。 同じマシン上だけでなく、ネットワーク上でも。