Hatena::ブログ(Diary)

miura1729の日記 このページをアンテナに追加 RSSフィード

2008-12-12

nbodyが動きました

20:12 |  nbodyが動きましたを含むブックマーク  nbodyが動きましたのブックマークコメント

yarv2llvmでnbodyが動きました。まだ、attr_accessorとかサポートしていないので、プログラムに手を加えています。

sample/bm_so_nbody.rbがソースです。(http://github.com/miura1729/yarv2llvm/tree/master/sample/bm_so_nbody.rb)

実行速度を測ってみました。N=200_000です。

Ruby 1.9

-0.169075164
-0.169083713

real	0m16.674s
user	0m16.577s
sys	0m0.108s

yarv2llvm

-0.169075163828524
-0.169083712569648

real	0m6.576s
user	0m5.982s
sys	0m0.592s

これは、コンパイル時間込みの場合です。その場合で2倍強、コンパイル時間が約2秒くらいなのでコンパイル時間を入れないと3倍強という感じです。fibだと30倍以上だったので、ずいぶんな速度低下です。インスタンス変数のアクセスとかRubyランタイムを呼びまくっているのでこんなものかなーと思います。インスタンス変数のアクセスをキャッシュするとかすると速度が上がるんじゃないかなと思っています。

それよりも、nbodyみたいな比較的複雑なプログラムでも型矛盾を起さずにコンパイルできてしまうことにびっくりです。

追記(2008/12/13)

インスタンス変数のlvalueをスタック上にキャッシュするようにしてみました。

-0.169075163828524
195827.292170961

real	0m5.342s
user	0m4.872s
sys	0m0.483s

ちょっと速くなるが答えが違う。おそらくバグが取れてもこれより速くなることは無いと思うのでこの方法でも5倍くらいまでしか行かないようです。この場合も型変換のオーバヘッドが残るのですが、これを何とかする方法が思いつきません。

ドキュメントに

「Real Programmers Don't Use Instance Variables」

とか

「Instance Variables Considered Harmful

とか書いておいたほうが効果があるのかもしれません。

追記2(2008/12/14)

バグが取れました。ポインタデリファレンスの回数を間違えていました。

-0.169075163828524
-0.169083712569648

real	0m5.333s
user	0m4.716s
sys	0m0.638s

スピードアップの方法を考えました。インスタンス変数型推論で決定したネイティブな表現で格納する配列を用意し、そのポインタをstruct RObjectのstruct st_table *iv_index_tblに格納するって方法です。llvmから復帰するときは、RCLASS_IV_INDEX_TBL(rb_obj_class(obj))で戻しておきます。

ささだささだ 2008/12/12 21:54 おお,意外.softtyping の成果でしたっけ?

miura1729miura1729 2008/12/12 22:28 softtypingになるんでしょうか?softtypingってよくわかっていないのですが、リテラルとかわかっている型を元に、同じ変数は同じ型、2項演算子は2つとも同じ型、結果も同じ・・・、って感じに同じ・おなじをつなげていって判断しています。それで判らない場合はVALUE型のデータということにして必要に応じて型変換しています。
これまで見る限りはメソッドの定義だけではなく呼び出し側の情報も判断すると、型が判らなくてVALUE型になっちゃうことはほとんど無くて、たいていはちゃんと型が決まるようです。ただ、ほとんどのRubyのCで書かれたAPIはVALUE型のデータを渡す必要があるのでAPIを呼び出すと型変換が必要になります。nbodyでは変数の型がdoubleと判っているのにrb_ivar_setを呼び出すためにrb_float_newを呼び出すコードが出力されていてかなり悲しくなりました。

トラックバック - http://d.hatena.ne.jp/miura1729/20081212/1229080379