Mitaka.rb #5 で「明日使える超高速 Ruby」を話してきた

10/22 に三鷹駅近くのモダンタイムスさんで行われた Mitaka.rb #5 に、三鷹クラスタの一員として のこのこ行ってきた。
主催の @ysakaki さん他関係各位ありがとうございました&お疲れ様でした。


Mitaka.rb ってどんなん?」という人には、→ @ysakaki さんのお料理写真いっぱいいっぱいの記事 をどぞ。食べ物は雄弁。


Mitaka.rb 参加は2回目。
前回 ( Mitaka.rb #3 pgcafe Nite! ) よりも三鷹率があがってる? 自宅から半径 100mなご近所さん話題とか、三鷹〜調布間のローカルネタでずいぶんもりあがることができた。
また .rb なだけあって、Windows 7 を褒め称えたり、Boost をケナしたり、Delphi を熱く語ったり、と Ruby な話題にも事欠かなかった。


歓談&おいしい食事のあとのLTコーナーで「明日使える超高速 RubyRubyXbyak 〜」という話をさせてもらって、三鷹方面に "Xbyak" が読める人を20人ほど増やしてきた。
ちなみに前回は「Javascript で Ruby の作り方」



なにがどう「明日使える」のかは資料を見てもらうとして、ネタである "RXbyak" について簡単に紹介。


RXbyak は、ネイティブコードを生成する C++ ライブラリである Xbyak (光成さん作) を Ruby から使えるようにした Ruby 拡張である。


つまり、どこからどうみても Ruby にしか見えないこのコードが、動く。

require 'RXbyak'

rx = RXbyak.new
rx.mov :eax, [:esp, 8]        # mov eax, (esp+8)  // 第1引数のポインタ
rx.movq :xmm0, [:eax]         # movq xmm0, (eax)
rx.mov :eax, [:esp, 12]       # mov eax, (esp+12) // 第2引数のポインタ
rx.movq :xmm1, [:eax]         # movq xmm1, (eax)
rx.mulsd :xmm0, :xmm1         # mulsd xmm0, xmm1  // かけ算
rx.mov :eax, [:esp, 4]        # mov eax, (esp+4)  // 返値のポインタ
rx.movq [:eax], :xmm0         # movq (eax), xmm0
rx.ret                        # ret

puts rx.call(256.0, 256.0)    # => 65536.0
puts rx.call(123.45, 678.9)   # => 83810.205


……とまあ、(例によって)ちょっとお馬鹿なことを全力でやるニコニコ系LTだったわけだが、この「どこからどうみても Ruby にしか見えない」キモかわいいコードを見ているうちに、なんかこれはこれでアリかな、という気になってくるw


Ruby が遅いのは承知の上で、それでも Ruby を使うのは、その人にとっては開発が短時間で済むとか、Ruby の記述の柔軟性とか、そういうポイントがあるわけだ。
だから、C/C++ で書けば速くなることはわかっていても(そしてそのスキルがあったとしても)、はいそうしましょう、というわけにはなかなかいかない。
それに本当に速くしたい部分はごくごく一部、他は Ruby のままでかまわない、ということも往々にしてある。


RXbyak はそんな「Ruby のままで速くなる方法」の一つになれる、かも?
他にも RubyInline という Ruby コードの中に C を書ける拡張があるが(知らなかったw。会場で id:akasata さんに教えてもらった)、JIT(動的生成) & アセンブラ(SIMD うはうは)というあたりは RXbyak の魅力かな。
あと、コンパイラ揃えるのが面倒でまだ試してないけど、RXbyak は Windows でも動く(はず)。


それから、この手の言語生成技術はただでさえややこしい&見通しが悪くなりやすいので、できるだけ短く書ける、やわらかいコードで行う方がいい気がする。って、それなんて Ruby


とまあ、そんな妄想を抱こうにも、いまはまだ実装率が低すぎて上のサンプルくらいしか動かないwww
Ruby 拡張は初挑戦なのに、C++ ライブラリである Xbyak を組み込もうというのは少々無謀(Ruby 拡張は C で書くのが原則)。
しかも思いついて実装を始めたのが日曜日から、なぁんてタイトなスケジュールでは、サンプルが動いた後は資料を作るのがやっと。


そのうち、ニューラルネットワーク実装を RXbyak で動かすあたりまでは最低限作り込むつもりだけど、まずは明日の PRML 読書会の予習だ〜。

(蛇足) ネタがわからない人向けの解説。

  • RXbyak は、アセンブラを動的に生成するコードが Ruby で書けるようになる拡張。上のサンプルコードは Ruby DSLx86 アセンブラを書いている。
  • JIT とは、元となるプログラムなどから動的にネイティブコード(=マシン語)を生成すること。実行時に与えられるデータを使って最適化などできるので、C/C++ で素直に書くより速くなることが期待できる。正規表現の実装などでは普通に用いられている。
  • 普通のプログラムは汎用的に(どのCPUでも)動くことを考慮して、CPU の新しめの機能を使い切ってはいない(現行のほとんどのパソコンが対応していても)。それらを使うにはアセンブラ(あるいは同等のコード)を書くしかない。
  • MSX べーしっ君」とは同名のマンガに由来する MSX のベーシックコンパイラ。BASIC のプログラムを実行時に Z80 マシン語に変換して、高速動作していた。このネタで笑ってくれた人は相当(ry

蛇足その2

おっとコードの在りか貼るの忘れてた。現時点で動かしたい物好きがいるかどうか怪しいけどw

ruby extconf.rb ; make で RXbyak.so ができるので、あとは適宜。
ちゃんとした環境を作っている余裕がなくて、最も手近な環境で作ってたので動作確認したのは Linux / gcc 3.4 / Ruby 1.8 の組み合わせのみ。
Windows(VC) と gcc 4 は動くことを期待はしているけど、まあそのうち。