[前][次][番号順一覧][スレッド一覧][生データ]

yarv-dev:631

From: SASADA Koichi <ko1 atdot.net>
Date: Fri, 30 Sep 2005 22:10:41 +0900
Subject: [yarv-dev:631] Re: thread support

 ささだです。

SASADA Koichi wrote:
>  ささだです。
> 
>  pthread 限定ですが、スレッドの対応をしてみました。VM ごとにジャイアン
> トロックを持つ方法です。まだ、I/O とかプロセスとか、ブロックするところの
> 対応はあまりしていないのですが。

 いくつかの実装方法があると思うので、その辺をまとめてみたいと思います。

mode 1) ユーザレベルで全部やる
mode 2) ネイティブスレッド利用+ジャイアントロック
mode 3) ネイティブスレッド利用+細粒度ロック

(ネイティブスレッドは OS、またはライブラリが提供すると想定)

 を考えています。


mode 1) ユーザレベル

 従来どおり。

 各 Ruby スレッド = VM が管理するオブジェクトが並行に実行するモデル。複
数 CPU がある場合、各スレッドは並列実行することが出来ない。

 ただし、もしネイティブスレッドが利用できる環境ならば、プロセス内に独立
した複数の VM をつくり、それらを並列実行することは可能。

 スレッドが切り替わるタイミングは完全に VM が管理できるので、排他制御な
ど、難しい話は考えなくても良いが、ブロックする処理(プロセスの wait、I/O
など)を VM はきちんとブロックしないように面倒見てあげなければならない。

 スレッドスケジューリングはユーザレベルで行わなければならない。


mode 2) スレッドライブラリ利用+ジャイアントロック

 [yarv-dev:629] check interrupt timing で述べたとおり。

 各 Ruby スレッド = ネイティブスレッドが並行・並列に実行するモデル。複
数 CPU がある場合、各スレッドは並列実行することが出来ない。

 ただし、プロセス内に独立した複数の VM をつくり、それらを並列実行するこ
とは可能。

 スレッドが切り替わるタイミングは完全に VM が管理できるので、排他制御な
どは(多分)必要ない。ブロックする処理も、ネイティブスレッドが全部面倒見
てくれる(はず)なので考えることはとても少ない。また、スレッドスケジュー
リングも全部お任せ。ただし、自由度は減ることになる。


mode 3) スレッドライブラリ利用+細粒度ロック

 各 Ruby スレッド = ネイティブスレッドが並行・並列に実行するモデル。複
数 CPU がある場合、並列実行可能。スレッドの切り替わるタイミングは任意。

 オブジェクトに対する操作で、いろいろと排他制御を付ける必要がある。

 たとえば、String オブジェクトの RSTRING(str)->ptr のような操作は排他制
御が必要になる(これを全部排除しようとすると大変...)。これは、例えば
ptr を取得したあと、スレッドスイッチが起こり、他のスレッドが str に対し
て破壊的操作をして、ptr が指しているメモリオブジェクトを REALLOC なりし
た場合、元のスレッドが free したメモリオブジェクトを参照してしまいます。

ThreadA
  ptr = RSTRING(str)->ptr;
ThreadB (switch)
  RSTRING(str)->ptr = other_memory_location;
ThreadA (switch)
  ptr[0]; /* error! */

 そのようなことが起こらないように、細かく排他制御を行わなければならな
い。(排他制御を行わないが高速な実装を提供し、Ruby ユーザの責任、とする
ことも出来るが、処理系として正しいかは謎)。

 排他制御のための変更も大きい。先ほどの例では

 sprintf(buff, "%s\n", RSTRING(str)->ptr);

 というプログラムは

 LOCK(str);
  sprintf(buff, "%s\n", RSTRING(str)->ptr);
 UNLOCK(str);

 としなければならず、煩雑で、修正箇所はとても大きい。


 排他制御の粒度は、時間的には細かいが、ロックをジャイアントロックにして
もいいし、操作ごとに用意したロックでもいいし(たとえば String などのクラ
スごとにロックを用意)、オブジェクトごとにロックを利用してもよい。

 並行 GC を実装する必要がある。

 スレッドスケジューリングはネイティブスレッドにお任せ。I/O などもお任せ。

(この辺を考え出すと、JavaVM みたいなものを想定するんだろうか)


------------------------------------------------------------------

 まとめ、比較をしてみます。m1, m2, m3 をそれぞれ mode 1, 2, 3 とよんで
ください。


・スケーラビリティ

 m3 >> m2 > m1

 パラレルに走れれば台数効果が期待できます。m2, m1 は同じレベルですが、
multi-VM への可能性から m2 > m1 としました。


・シングルプロセッサでの性能

 m2 > m1 > m3

 ネイティブスレッドに任せたほうがスレッドスイッチ、スレッド管理、スレッ
ド生成 I/O 管理などの効率はよいことが期待出来ます。m3 は排他制御がかな
り必要になるため、並列実行ができなければ m2 よりも性能が落ちることが予想
されます。シングルプロセッサ環境で m3 をやる意味はないでしょう。

 ただし、スレッド生成などのプリミティブな操作については現状のユーザレベ
ルスレッドのほうが効率がよさそうです。スレッドを生成しては捨てるようなプ
ログラムでは m1 が有利でしょう。


・実装の容易さ(バグの出にくさ)

 m2 > m1 > m3

 m2 は I/O などブロッキングを考える必要が無い点で楽です。m1 はそれを考
えなければいけない。m3 は任意の時点での排他制御をきっちりしないと動かな
いので、大変です。また、GC なども面倒そうです。


・生成するスレッドの数の制限

 m1 > m2 = m3

 1 ネイティブスレッド = 1 Ruby のスレッドだと、ネイティブスレッドの生成
上限(たとえば、cygwin では 700 個強でした)に制限されます。

 m1 はメモリが許す限り生成できます(ただし、なかなか順番が回ってこない)。

 Ruby プログラムはいくつくらいのスレッド生成が期待されてるんでしょう
か。スレッドプールを作って Queue で通信、がいいような気がしますが。


・I/O 性能

 m3 > m2 > m1 (??)

 これは良くわからない。OS などが頑張ってくれるから、これでいいと思うの
だけれど。ネイティブスレッドの実装によるかな。

 m3 > m2 なのは、m2 ではブロッキングが解除されても、任意のタイミングで
スレッドに処理が渡らないため。


・拡張ライブラリとの親和性

 m2 > m3 > m1 (??)

 何かブロックする処理をする操作を含む拡張ライブラリを今の Ruby のスレッ
ド対応するのは大変です(ネイティブスレッドを別に作って対応?)。そのた
め、YARV でネイティブスレッド対応する、と言ったときにこういう場合に楽に
なるね、と喜ばれたことがあります。

 m2 > m3 なのは、拡張ライブラリももちろん排他制御を考えなければならず、
煩雑なためです。

 その拡張ライブラリ自身がスレッドを使っていた場合は未知数。複数の GC の
共存よりは楽かな。

------------------------------------------------------------------

 こんなところでしょうか。評価軸や評価に見落とし・事実誤認などあればご指
摘ください。

 また、今後の開発方針などに対してご意見などあればご教示ください。


 エンタープライズ用途(CPU を 8 つとか積んでるマシンで 1 つの Ruby プロ
セスをぶん回す、など)では m3 がよさそうですが、そもそも Ruby でそういう
リクエストはあるのか。それだったら複数プロセッサで dRuby で通信、などの
ほうがよさそうに思える。mod_ruby はどうなんだろう。そもそも、エンタープ
ライズ分野では SMP 構成よりはクラスタ構成のほうが主流な気がするが、どう
なんだろう。

 この辺のニーズの把握って、たとえば NaCl さんなんかでは何かデータあった
りしますか。

 Java では頑張って m3 をやってますよね。やれたらあっちのほうがかっこい
いんだろうけれど。

 デュアルコアなんかを考えると、m3 にしていかないと今後まずいのかなー、
という気もします。


 現実的には m2 がいいんでしょうかねぇ。Sydney と同じとも言えるかも。

 きちんと m2 で作りこんでから、あらためて m3 を目指すのでもいいかも。


(未踏の落としどころも考えなければ...。申請書では m3 をやる、みたいに書
いてしまったが、かなり大変そう。あ、今申請テーマ概要を確認したら、ネイ
ティブスレッド対応としか書いてないな。m2 でもよさそう)。

-- 
SASADA Koichi at atdot dot net

--
ML: yarv-dev quickml.atdot.net
使い方: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]

       628 2005-09-30 20:11 [ko1 atdot.net       ] thread support                          
->     631 2005-09-30 22:10 ┣[ko1 atdot.net       ]                                       
       633 2005-09-30 23:35 ┃┣[matz ruby-lang.org  ]                                     
       635 2005-10-01 23:41 ┃┃┗[ko1 atdot.net       ]                                   
       636 2005-10-02 10:58 ┃┃ ┗[shiro lava.net      ]                                 
       638 2005-10-02 18:15 ┃┃  ┗[ko1 atdot.net       ]                               
       640 2005-10-02 19:05 ┃┃   ┗[shiro lava.net      ]                             
       641 2005-10-02 21:23 ┃┗[shudo computer.org  ]                                     
       643 2005-10-03 09:33 ┃ ┗[ko1 atdot.net       ]                                   
       632 2005-09-30 23:28 ┗[matz ruby-lang.org  ]                                       
       634 2005-10-01 23:30  ┗[ko1 atdot.net       ]