QA@IT

RubyのGILはなぜ必要なのですか?

5212 PV

http://www.jstorimer.com/2013/03/26/brian-shirai-threads.html

を読んでいて思ったのですが、GILは空気のような当たり前の存在になっているためか、思考停止していて、そのありがたさがわからなくなっていることに気が付きました。

単純に考えれば、せっかくRuby 1.9以降はネイティブスレッドになったのだから、GILをなくせばマルチコアを活かせるようになるので、アプリケーション設計の選択肢が大きく広がるように思えます。

また、GILのある現在でも、グローバルなステート(定数、グローバル変数、クラス変数など)やファイルアクセスなど外部リソースに対するレースコンディションは無数に存在するので、GILがあれば全て解決、というようなものでもなさそうです。

また、WikipediaのGILの項目をみても、採用している代表例はCPythonとMRI Ruby程度であり、すごく一般的に有用だと評価されているアプローチというわけでもなさそうです。

どちらかというと、GILの存在によって、マルチスレッドによる並列制御を書くことを諦めさせて、forkベースのマルチプロセスにいかざるをえないという、フィーチャー自体ではなく間接的な効能によってスレッドセーフティが達成されているような印象を受けます。

そこで改めて質問なのですが、RubyのGILはなぜ必要なのでしょうか?GILがないと、どのような場合に困るのでしょうか?

使うライブラリも含めて、スレッドセーフティに関する責任をユーザがとれると判断したのであれば、GIL.disableのようなオプションがあってもよさそうな気がするし、現場での多様性をいかした実験ができると思うのですが、そういうオプションが提供されていないのには、どのような理由があるのでしょうか?

回答

すでに回答がついてるのと、まつもとさんや、ささださんが既に詳細に書かれていますが、

理由は大きく3つありまして、

  1. 現在の CRuby が (C レベルで) スレッドセーフではない
  2. 現在、そして将来の C 拡張ライブラリは (きっと) スレッドセーフには作られない(し、作ったつもりでもバグってるに決まってる)
  3. 上記の対策でロックを随所に入れると、シングルスレッド性能が落ちる

上記 1. の具体例としては、まず正規表現実装である鬼車/鬼雲は現在 thread unsafe で入れています。コンパイルオプションで thread safe にはできるんですが、すると 3. の通りシングルスレッド性能が落ちます。ハッシュ実装である st も thread unsafe なのでロックしないと最悪 SEGV します。

結局、akr さんの仰られているとおり、単純になくすとレースコンディションってレベルではすまず SEGV してしまうし、頑張ってなくしても C 拡張ライブラリがあるからそこで SEGV するだろうって話になるので、 C 拡張ライブラリとの親和性をとてもとても重視している CRuby というプロダクトのデザイン上の決定としては、GVL を外すという判断はあまり簡単ではありません。

編集 履歴 (1)
  • ありがとうございます。具体的な例をいただけたので理解が進みました。むしろスレッドアンセーフと割りきってロックフリーで性能をかせぐ、という面も大きいということですね。鬼雲の切り替えがコンパイルオプションでしか選べないのだと、GIL.disableみたいな大域設定は無理そうですね。だんだんイメージわいてきました。 -

単純にGVLを外すと、Cで書かれたRubyの言語処理系の大部分をスレッドセーフにしなければならず、また将来にわたってもスレッドセーフなコードを書き続けなければいけないし、これは大変そうなのでやれていないのかなぁと理解しています。

どうてしてもGVLを外して並列で実行したい!ということであれば、C拡張ライブラリでrb_thread_call_without_gvl()を使うという手もあると思います。
実際、拡張ライブラリのzlibでは特定の処理をGVLを外して実行しています。

編集 履歴 (0)
  • なるほど。どちらかというとCRubyの実装上の都合というのが大きいということでしょうか。zlibのようなCPU集約的な処理でGILをリリースしてくれるのは嬉しいですね。ありがとうございます。 -

単純になくすと、SEGV などの異常動作をしてしまうからではないでしょうか。

編集 履歴 (0)
  • ありがとうございます。いまでもC拡張ライブラリの書き方次第でSEGVすることはあると思うのですが、GILのある・なしによる具体的な差分を知りたかったのです。。。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。