ao benchを高速化しているのですが、うまく行かない
今は、なんだかんだ忙しいのであまりプログラムをいじっていないのですが、時間があるとao benchを高速化することに凝っています。いろいろ試しているのですが、いまいち効果がでません。
例えばこんなことを試してみました。
- インスタンス変数はGCの関係上BOX化した形式(VALUE)で格納する必要がある
- こうすると、浮動小数点型のデータを扱うと、インスタンス変数の代入のたびにFloatオブジェクトをアロケートする必要がある。
- ところで、インスタンス変数が浮動小数点型であると型推論できると代入の際には元のインスタンス変数にはFloatオブジェクトが格納されているのを保障できる。また、このFloatオブジェクトは他の場所から指さないことも保障できる。
- そのため、Floatオブジェクトを新たにアロケートする代わりに元のインスタンス変数に入っているFloatオブジェクトを再利用するようにすると、速度がアップするんじゃないかなと考えた。
- 試してみたが、1%くらいしか(2分中2秒くらい)速度が上がらない。
なぜだーー、と思いついかっとなって http://d.hatena.ne.jp/miura1729/20090512/1242123708 で使ったGC profiler起動オプションを使ってみました。
ruby19 yarv2llvm.rb --gc-profile sample/ao-render.rb > ao.ppm GC 2685 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 0.219 655920 1425408 71253 0.00000000000000000000 2 0.281 696520 1441792 72072 0.00000000000000000000 3 0.469 713680 2572288 128583 16.00000000000001421085 4 0.891 728540 4227072 211302 15.00000000000001421085 5 1.360 773540 4243456 212121 14.99999999999990230037 中略 2666 130.969 906800 4866048 243243 15.99999999999113242666 2667 131.016 906880 4866048 243243 14.99999999998635757947 2668 131.063 906920 4866048 243243 14.99999999998635757947 2669 131.110 906840 4866048 243243 14.99999999998635757947 2670 131.156 906900 4866048 243243 16.00000000001955413609 2671 131.203 906760 4866048 243243 16.00000000001955413609 2672 131.250 906940 4866048 243243 0.00000000000000000000 2673 131.281 906940 4866048 243243 16.00000000001955413609 2674 131.328 906820 4866048 243243 16.00000000001955413609 2675 131.375 906920 4866048 243243 16.00000000001955413609 2676 131.422 906960 4866048 243243 15.99999999999113242666 2677 131.469 906860 4866048 243243 15.99999999999113242666 2678 131.516 906860 4866048 243243 14.99999999998635757947 2679 131.563 906900 4866048 243243 14.99999999998635757947
見てみると、1秒間に20回くらいGCが起動されて最終的に1/3がGCで費やされています。オブジェクトのアロケーションも含めると2/3がメモリ操作じゃないかなと思います。やはり、エスケープ解析必要かなと思います。オブジェクトの寿命を掴んで再利用したりとか。
追伸
BOX化されたデータを箱入りデータと呼ぶのはどうでしょう?
追記
Floatオブジェクトの再利用はnbodyでは効果があるみたいです。
Floatオブジェクトの再利用をいれた場合
time ruby19 yarv2llvm.rb bm_so_nbody.rb -0.169074947 -0.169083520 real 0m5.073s user 0m4.544s sys 0m0.310s
Floatオブジェクトの再利用をいれた場合のコンパイル時間
time ruby19 yarv2llvm.rb --compile-only bm_so_nbody.rb real 0m3.826s user 0m3.404s sys 0m0.342s
Floatオブジェクトの再利用をいれない場合
time ruby19 yarv2llvm.rb bm_so_nbody.rb -0.169074947 -0.169083520 real 0m6.414s user 0m6.059s sys 0m0.310s
Floatオブジェクトの再利用をいれない場合のコンパイル時間
time ruby19 yarv2llvm.rb --compile-only bm_so_nbody.rb real 0m3.784s user 0m3.451s sys 0m0.311s
Ruby 1.9.2 で実行した場合
time ruby19 bm_so_nbody.rb -0.169074947 -0.169083520 real 0m16.602s user 0m16.405s sys 0m0.093s ruby19 -v ruby 1.9.2dev (2009-05-06 trunk 23350) [i386-cygwin]