Direct threadingってよく聞くんだけどどういうものか知らなかったので調べた。
- threaded codeは、VMの実装をするときに命令のフェッチ→オペコードによって処理の分岐というのを、プログラム側に各オペコードの処理のアドレスを埋め込んで高速化する技のこと
- threaded codeで実装するとコンパクト、だけど遅い。 でも小さいから場合によってはキャッシュミスが減って十分速いかも。
- threaded codeはVMのバイトコードから実際の関数だかサブルーチンのアドレスを直接埋め込みをコンパイル時やプログラムロード時に行って、実行時は直接そのアドレスに飛ぶようにしたもの
- しかしバイトコードよりは使う空間が大きくなる
- direct threaded codeは、次の命令への分岐を先頭の一ヶ所で行わず、各オペコードの処理の最後で先頭に戻る代わりに次の命令に直接ジャンプする
- YARV Maniacs 【第 3 回】 命令ディスパッチの高速化
- threaded codeだと分岐予測がほぼはずれる、のでdirect threadedはその分有利
テストのプログラムを書いた(GCC拡張のgotoのラベルのアドレスを取る機能を使って)
/// VMのオペコード |
cygwin上でgcc -O2 でコンパイルした実行結果:
$ time ./thread.exe |
だめじゃん。 gcc -Sでアセンブリコードを見てみるとDIRECT_THREADEDでもディスパッチ部がひとつにまとめられてdirect threadedになってない。
; ディスパッチ部 |
gcc -S で出力された.sを直接書き換えてdirect threadingにして実行してみる:
$ time ./real-direct.exe |
おお、確かに速くなった。 ジャンプ命令ひとつでこれだけ変わるというのは致命的かも。
.p2align 4,,7
は、最大7バイト挿入して16バイトにアライメントする、ということらしい。 ページにあわせると命令キャッシュに乗って?有利とか何とか。 勝手にやってくれるんか。- Threaded Code
Direct threadingでフィボナッチ計算
上のVMにいくつかてきとーに命令を足してフィボナッチ計算(30)をさせてみた:
/// VMのオペコード |
threaded code の実行結果
$ time ./fib-threaded 30 |
direct threaded code の実行結果
$ time ./fib-direct 30 |
Cとか、他のスクリプト言語での実行結果
Cネイティブと、ゲームにおけるスクリプト言語の現状に出てきたスクリプト言語、あとはSchemeで速度検証。 Celeron 650MHz。
言語 | real | user | sys |
---|---|---|---|
gcc | 0m0.136s (1.00) | 0m0.100s | 0m0.040s |
threaded | 0m0.817s (6.01) | 0m0.771s | 0m0.050s |
direct-threaded | 0m0.439s (3.23) | 0m0.400s | 0m0.030s |
Lua | 0m2.060s (15.15) | 0m2.032s | 0m0.040s |
Squirrel | 0m12.117s (89.10) | 0m12.117s | 0m0.020s |
xtal | 0m2.874s (21.13) | 0m0.020s | 0m0.020s |
Gauche | 0m1.661s (12.21) | 0m0.020s | 0m0.030s |
Ypsilon | 0m1.593s (11.71) | 0m0.010s | 0m0.040s |
YpsilonだけはWin32バイナリ版で他はCygwin上でソースをコンパイルしたもの。 純粋に計算だけだから、それほど問題ないよね。
Squirrelの遅さは異常。 これはリファレンスカウンタ方式によるものなのか?コンパイルオプションを見てもちゃんと-O2でやってるし。 もしも文法とか機能が飛びぬけてよかったとしても、遅い言語には興味ありません! Xtalが結構速いのが驚き。
CRIScriptはとにかくデカすぎる、boostとか入ってるもんだから。 組み込むのはちょっと辛い。 そしてVisualStudioのプロジェクトしかついてなくて、Cygwinから簡単にコンパイルできない。 今使ってる旧マシンで動かそうとしたけど、Visual C++ 2008 Express Editionのインストールがうまくいかず断念 Ypsilonは以前試したときはGaucheの2倍くらいの速度が出たんだけど、今回はシングルコアで動かしたせいかな?
ということで、これから使うべき組み込みスクリプト言語はSchemeという結論が出たようだな!