Ricsin: RubyにCを 埋 め 込 むシステム Ricsin: A System for C Mix-in to Ruby 東 京 学 学 院 情 報 理 学 系 研 究 科 創 造 情 報 学 専 攻 笹 耕 / ささだ こういち sasada@ci.i.u-tokyo.ac.jp 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 1
Agenda 背 景 : 現 状 のRubyとC 拡 張 ライブラリ 提 案 :Ricsin: RubyにCを 埋 め 込 むシステム 従 来 に べ, 書 きやすく, 低 オーバヘッド Ricsin の 利 例 と 処 理 の 流 れ Ricsin の 記 法 Ricsin の 設 計 と 実 装 評 価 と 考 察 関 連 研 究 まとめと 今 後 の 課 題 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 2
Ricsin 記 法 での 記 述 例 def open_fd(path) # Ruby での 記 述 fd = C (%q{ /* C での 記 述 */ return INT2FIX(open(RSTRING_PTR(path), O_RDONLY)); }) raise 'open error' if fd == -1 yield fd ensure raise 'close error' if -1 == C (%q{ /* C での 記 述 */ return INT2FIX(close(FIX2INT(fd))); }) end 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 3
背 景 :Ruby オブジェクト 指 向 スクリプト 語 Ruby 最 新 版 Ruby 処 理 系 Ruby 1.9.1 もっとも 利 されているRuby 処 理 系 200x 年 y リリース 予 定 1.9 からは 仮 想 マシン(VM)を 搭 載 (YARV) C 語 で 実 装 されているので CRuby と 表 記 Eg. JRuby, IronRuby, Rubinius Cで 開 発 されているので,Cで 処 理 を 拡 張 可 能 組 み 込 みクラスやメソッド C 拡 張 ライブラリ( 動 的 リンクライブラリ) 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 4
背 景 :RubyからCの 機 能 を 利 Cでないと 記 述 できない 処 理 システム 依 存 の 処 理,レガシーなライブラリの 利 Ruby 処 理 系 に 踏 み 込 まないと 記 述 できない 処 理 Rubyでは 性 能 でない 処 理 Cで 記 述 したメソッドを 集 めたC 拡 張 ライブラリ Cでメソッドを 記 述 Cメソッド(vs. Rubyメソッド) つまり,Ruby C の 遷 移 は メソッド 単 位 CメソッドからRubyメソッドを 呼 ぶことも 可 能 Ruby C APIを 利 して 記 述 C だけで 考 えるとそれなりに 書 きやすい 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 5
背 景 :C 拡 張 ライブラリの 作 成 と 利 extconf.rb Ruby C APIで Cメソッドを 記 述 Cファイルで 定 義 した Cメソッドを 利 用 するように 記 述 Makefile Cファイル (C) rbファイル (Ruby) C ビルド 環 境 (C compiler, etc) soファイル (C 拡 張 ライブラ)リ 実 行 に 必 要 なファイル CRuby 読 込 実 行 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 6
現 状 のC 拡 張 ライブラリ 作 成 の 問 題 点 1. 記 述 性 の 問 題 :RubyとCをメソッド 単 位 で 分 割 CとRubyでファイル 分 割 が 必 要 メソッドより 細 かい 粒 度 での 処 理 が 記 述 できない 処 理 が 必 要 な 箇 所 に 直 接 記 述 できない 例 外 処 理 やブロック 呼 び 出 しなど,Rubyで 書 いた が 圧 倒 的 に 簡 単 な 処 理 もCで 書 かなければならない 2. 性 能 の 問 題 : 必 ずメソッド 呼 び 出 しが 必 要 必 ずフレーム 成 のオーバヘッドが 必 要 Ruby C の 呼 び 出 し C Ruby の 呼 び 出 し(VM 再 帰.こっちの が 重 い) イテレータを C で 実 装 するとこうなることが 多 い 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 7
Ricsin: RubyにCを 埋 め 込 むシステム 提 案 :RubyにCを 埋 め 込 むシステムRicsin 記 述 性 を 向 上 :Rubyプログラム 中 にCを 記 述 RubyにCプログラム を 直 接 埋 め 込 む 書 式 Rubyのコンテキスト 情 報 をCプログラム から 直 接 参 照 性 能 を 改 善 :VM 命 令 を 新 設 し 呼 び 出 しコスト 削 減 Ruby C の 遷 移 をVM 命 令 / 関 数 呼 び 出 しコストで メソッドの 般 化 が 不 要 で 特 殊 な 決 めうちが 可 能 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 8
Ricsinの 利 例 Cでないと 記 述 できない 処 理 を,Ricsinでは: システム 依 存 の 処 理,レガシーなライブラリの 利 必 要 な 箇 所 に 必 要 な 処 理 を 直 接 Cで 埋 め 込 み Ruby 処 理 系 に 踏 み 込 まないと 記 述 できない 処 理 RubyにRuby C APIを 直 接 埋 め 込 み 例 :Ruby 処 理 系,Ruby C APIのテスト Rubyでは 性 能 でない 処 理 Rubyに 直 接 Cを 埋 め 込 み, 継 続 的 速 化 記 述 性 の さ, 効 率 の 良 さ 相 互 に 影 響 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 9
Ricsinの 全 体 像 rcbファイル (Ruby+C) Ricsin 変 換 器 Makefile Cファイル (C) rbファイル (Ruby) C ビルド 環 境 (C compiler, etc) soファイル (C 拡 張 ライブラ)リ 実 行 に 必 要 なファイル 読 込 実 行 Ricsin 対 応 CRuby 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 10
Ricsin 記 法 Ricsin 記 法 :Ruby + C 混 在 プログラム 記 述 記 法 ファイルの 拡 張 はrcb(rb に c を 埋 め 込 んだ) 完 全 に 有 効 なRubyプログラムとして 設 計 Rubyパーサ, 検 証 器 をそのまま 利 可 能 C などの 特 定 のメソッド 呼 び 出 しを C プログラム 埋 め 込 み 指 として 利 字 列 リテラルでCプログラムを 指 定 埋 め 込 んだCプログラム は 若 変 換 埋 め 込 んだCプログラム 中 からはRubyの 環 境 がそのまま 参 照 可 能 Ruby C APIを 利 したCプログラム 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 11
Ricsin 記 法 での 記 述 例 def open_fd(path) # Ruby での 記 述 fd = C (%q{ /* C での 記 述 */ return INT2FIX(open(RSTRING_PTR(path), O_RDONLY)); }) raise 'open error' if fd == -1 yield fd ensure raise 'close error' if -1 == C (%q{ /* C での 記 述 */ return INT2FIX(close(FIX2INT(fd))); }) end 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 12
Ricsinで 利 するレシーバ C Cプログラム をその 場 に 埋 め 込 み Cdecl 関 数,マクロ,グローバル 変 数 定 義 を 記 述 Cinit ロード 時 に 度 だけ 実 する 処 理 を 記 述 Cb RubyのブロックをCで 記 述 Ccont Cの 中 にRubyを 記 述 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 13
Ccont Cの 中 にRubyを 埋 め 込 み CとRubyを 並 べるための 指 Ccont 便 利 な 省 略 記 法 を 意 ただし,Cの 変 数 スコープは 切 れる Rubyのローカル 変 数 で 値 を 共 有 v = true Ccont ('while (v!= Qnil) {') # (a) v = nil # (b) Ccont (' rb_p(v);') # (c) Ccont ('}') # (d) v = true #C while (v == Qnil) { /* (a) */ v = nil # (b) #C rb_p(v); /* (c) */ #C } /* (d) */ 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 14
コンテキスト 情 報 へのアクセス CからRubyのコンテキスト( 変 数 ) 情 報 へ 直 接 アクセス 可 能 ローカル 変 数 (lv) インスタンス 変 数 (@iv),グローバル 変 数 ($gv) 等 定 数 self 擬 似 変 数 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 15
コンテキスト 情 報 へのアクセス 例 def open_fd(path) # Ruby での 記 述 fd = C (%q{ /* C での 記 述 */ return INT2FIX(open(RSTRING_PTR(path), O_RDONLY)); }) raise 'open error' if fd == -1 yield fd ensure raise 'close error' if -1 == C (%q{ /* C での 記 述 */ return INT2FIX(close(FIX2INT(fd))); }) end 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 16
変 換 と 実 rcb -> C+Rubyに 変 換 rcbファイルをパースして, 埋 め 込 みCを 抽 出 埋 め 込 み 式 をCの 関 数 (*1)に 変 換 変 換 プロセスの 詳 細 は 省 略 実 時, 埋 め 込 み 式 の 実 専 VM 命 令 opt_ricsin_callを 新 設 (VM 唯 の 修 正 点 ) (*1) の 関 数 ポインタを 渡 すようにバイトコードコンパイル Cメソッド 呼 び 出 しからVM 命 令 実 + 関 数 呼 び 出 しに この 命 令 は,VM 命 令 を 拡 張 する 命 令 ということも 可 能 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 17
変 換 と 実 (cont.) # rcb ファイル v = 42 r = C (%q{ /* 埋 め 込 み C ボディ 部 */ rb_p(self); /* main と 表 示 */ return INT2FIX( FIX2INT(v) + 1); }) p r #=> 43 と 表 示 バイトコードコンパイル 生 成 関 数 呼 び 出 し [ADDR] [INSN] [OPERAND] 0000 putobject 42 0002 setlocal v 0004 opt_call_ricsin <funcptr> 0006 setlocal r 0008 putnil 0009 getlocal r 0011 send :p, 1 0017 leave /* 生 成 されるCソースファイルの 一 部 */ #define v (cfp->lfp[3]) #define r (cfp->lfp[2]) VALUE ricsin_func_1( rb_control_frame_t *cfp) { const VALUE self = cfp->self; { /* 埋 め 込 み C ボディ 部 */ rb_p(self); return INT2FIX(FIX2INT(v) + 1); } return Qnil; } #undef v #undef r 拡 張 ライブラリに 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 18
Ccont の 変 換 v = true #C while (v == Qnil) { /* (a) */ v = nil # (b) # rb_p(v); /* (c) */ #C } /* (d) */ [ADDR] [INSN] [OPERAND] 0002 putobject true 0004 setlocal v 0008 opt_call_ricsin <funcptr> 0010 pop 0013 putnil 0014 setlocal v 0018 opt_call_ricsin <funcptr> 0020 leave 生 成 バイトコードコンパイル #define v (cfp->lfp[2]) VALUE ricsin_func_1( rb_control_frame_t *cfp) { switch (GET_PC()) { case 10: goto label_10; case 20: goto label_20; } { label_10:; while (v!= Qnil) {; /* (a) */ SET_PC(10); return Qnil; label_20:; rb_p(v); /* (c) */ }; /* (d) */ SET_PC(25); return Qnil; } } return Qnil; } 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 19
成 されたC 語 ファイルのレイアウト rcb 1 ファイルにつき 1つのCファイルを 成 ( 詳 細 は 割 愛 ) ヘッダファイル 等 Cdecl で 埋 め 込 まれた 定 義 C, Ccont で 埋 め 込 まれた Cプログラム 片 を 変 換 した 関 数 群 実 行 するために 必 要 な データ 定 義 拡 張 ライブラリ 初 期 化 関 数 ( Cinit 含 む) 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 20
評 価 主 に 性 能 に 関 する 評 価 評 価 環 境 評 価 環 境 1:Intel Xeon E5335, Linux 評 価 環 境 2:SPARC T2, SunOS 5.10 傾 向 は 変 わらず.どちらでも 実 できることを すため. 評 価 項 1. Cの 機 能 呼 び 出 しの 実 時 間 較 2. イテレータの 速 化 の 例 3. 列 計 算 の 速 化 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 21
評 価 :Cの 機 能 呼 び 出 しの 実 時 間 較 空 のC 機 能 の 呼 び 出 し 時 間 の 較 空 のCメソッド 空 の C 評 価 環 境 1 (Intel) 評 価 環 境 2 (SPARC) C (sec) Ricsin (sec) C/Ricsin 0.44 0.05 8.8 4.56 0.44 10.4 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 22
評 価 :イテレータの 速 化 の 例 イテレータをRicsinで 書 き 直 し C: 従 来 Ricsin: Ccont を 利 して Ruby/C をミックス Ruby: Rubyで 書 き 直 し 評 価 環 境 1(Intel) 評 価 環 境 2(SPARC) 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 23
評 価 : 列 計 算 の 速 化 列 の 乗 算 ( 要 素 は 整 数 ) 12 のRuby Scriptを36 のCプログラム で 直 接 置 き 換 え 評 価 環 境 1 (Intel) 評 価 環 境 2 (SPARC) Ruby (sec) Ricsin (sec) Ruby/Ricsin 10.57 0.57 20.33 85.31 6.73 12.68 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 24
Ricsinに 関 する 考 察 Cを 埋 め 込 むと 度 な 最 適 化 が 出 来 ないのでは? 最 適 化 が 進 めばそうなるが,その 段 階 は 遠 い Cを 対 象 にしているためポータビリティも い 処 理 系 メンテナンスコストも 低 い 本 当 に 書 きやすいの? 数 であれば 従 来 のCメソッドより 書 きやすい エディタ 等 の 対 応 が 必 要 になるかも 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 25
関 連 研 究 C(とくに gcc)の asm (C + assembler) asm 中 に C は 記 述 不 可 能 HTML 埋 め 込 み 語 (PHP,JSP,JavaScript) Jeannie (OOPSLA 2007) Java+Cコードを 混 在 JavaとJNIコードを 成 Java C,Java Cは メソッド 呼 び 出 しに 変 換 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 26
関 連 研 究 :RubyInline (CメソッドをRubyスクリプトに 記 述 ) rbファイル (Ruby+C) 読 込 実 行 CRuby Cメソッド 定 義 を Rubyスクリプトに 直 接 記 入 Makefile 実 行 時 に 作 成 Cファイル (C) 動 的 読 込 ファイルがバラバラ という 問 題 点 だけ 解 決 C ビルド 環 境 (C compiler, etc) soファイル (C 拡 張 ライブラ)リ 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 27
まとめ RubyにCを 埋 め 込 むRicsinシステムを 提 案 メソッド 単 位 ではなく,Rubyに 直 接 Cを 埋 め 込 む 記 法 コンテキスト 情 報 に 直 接 アクセス 可 能 で 記 述 性 向 上 VMに 命 令 を 追 加 することで10 倍 速 なC 機 能 呼 び 出 し 今 後 の 課 題 C 部 分 を 真 にパースして 連 携 (の 検 討 ) AOTコンパイラとの 連 携 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 28
おわり ご 清 聴 ありがとうございました Ricsin: RubyにCを 埋 め 込 むシステム http://svn.ruby-lang.org/repos/ruby/branches/ricsin/ ささだこういち sasada@ci.i.u-tokyo.ac.jp ko1@atdot.net, ko1@rvm.jp 謝 辞 執 筆 に 協 して 下 さった 々 科 研 費 若 (スタートアップ)19800007 2008/10/28 Ricsin: RubyにCを 埋 め 込 むシステム 29