2008-12-19
binary_treesはくわせもの
|ふと、MagLevとyarv2llvmはどっちが速いんだろう?って思い調べてみました。
http://antoniocangiano.com/tag/maglev/
に、MagLevのbinary_treesの実行速度がRuby 1.8.6の結果とともに載っているのでこれと比べればいいやと考えました。
結果は、MagLevはRuby1.8.6の60.1秒に対して、7.7秒で約7.81倍です。
ところで、binary_treesは一見単純なプログラムですが、
と、yarv2llvmに厳しいプログラムです。
木のノードを表す配列には、数字,配列,nilが入ります。こういう場合、型推論は行わず(正確には型推論の結果を無視して)、型をVALUEとして扱うように変更しました。しかし、型をVALUEとして扱うと型変換のオーバーヘッドが入るのでエラーにするかVALUEとして扱うかオプションで選べるようにしました。
自己参照型構造体の形になっている配列は型を表示しようとすると、Array of Array of Array of ...と止まらなくなってしまいます。これは、この前のうさぎと亀の循環検知アルゴリズム(http://d.hatena.ne.jp/miura1729/20081130)で対応しました。
yarv2llvm, Ruby 1.8.7, Ruby 1.9.0で実行してみました。
yarv2llvm
stretch tree of depth 17 check: -1 131072 trees of depth 4 check: -131072 32768 trees of depth 6 check: -32768 8192 trees of depth 8 check: -8192 2048 trees of depth 10 check: -2048 512 trees of depth 12 check: -512 128 trees of depth 14 check: -128 32 trees of depth 16 check: -32 long lived tree of depth 16 check: -1 real 0m11.086s user 0m10.513s sys 0m0.592s
stretch tree of depth 17 check: -1 131072 trees of depth 4 check: -131072 32768 trees of depth 6 check: -32768 8192 trees of depth 8 check: -8192 2048 trees of depth 10 check: -2048 512 trees of depth 12 check: -512 128 trees of depth 14 check: -128 32 trees of depth 16 check: -32 long lived tree of depth 16 check: -1 real 1m53.655s user 1m53.405s sys 0m0.077s
Ruby 1.9.0
stretch tree of depth 17 check: -1 131072 trees of depth 4 check: -131072 32768 trees of depth 6 check: -32768 8192 trees of depth 8 check: -8192 2048 trees of depth 10 check: -2048 512 trees of depth 12 check: -512 128 trees of depth 14 check: -128 32 trees of depth 16 check: -32 long lived tree of depth 16 check: -1 real 0m35.207s user 0m30.655s sys 0m0.155s
これから、Ruby 1.8.7の10倍、Ruby 1.9.0の3倍くらいであることがわかります。でも、このyarv2llvmはずるをしていて、VALUE型のデータはチェックせずFixnumであると決め付けています。何もチェックしないでいきなり右シフトしています。そういうことで、多分、binary_treeに関してはMegLevと同じくらいといえるかと思います。
...、とここまでやった後MagLevの詳しいベンチマーク結果がありました。...思ったより速くない様な気がする・・・。複雑な機能をつけて速度が落ちていったのだろうか?明日はわが身です。
http://antoniocangiano.com/2008/12/09/the-great-ruby-shootout-december-2008/
追記
型衝突を起した場合、どの型で衝突が起きたか記録するようにしました。そうすることで、例えばVALUE型の足し算において、足し算に関係する型がFixnum(Int32Ty)だけだと判れば型チェックを省いていきなりシフト命令を出しても安全であることが(例えば、実はFloat型のデータが渡ってきてるとかそういうことは無いことが)、保障できます。
Rubyでも例外が出るような型エラー(nil + 1とか)はコアはいちゃいますが、そういうのはRubyでチェックしてもらうというスタンスです。
- 34 http://www.rubyist.net/~kazu/samidare/
- 2 http://a.hatena.ne.jp/fujita-y/
- 2 http://a.hatena.ne.jp/h_sakurai/
- 2 http://b.hatena.ne.jp/naoya/favorite
- 2 http://d.hatena.ne.jp/
- 2 http://k.hatena.ne.jp/keywordblog/YARV
- 2 http://reader.livedoor.com/reader/
- 2 http://s.hatena.ne.jp/mobile/miura1729/
- 2 http://www.google.co.jp/search?q=RubyVM+InstructionSequence+load&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja-JP-mac:official&client=firefox-a
- 2 http://www.google.com/search?hl=ja&lr=lang_ja&ie=UTF-8&oe=UTF-8&q=rubyでグラフ&num=50