先日Adobeから発表された、C/C++のコードをActionScriptで利用できるという Alchemy。いろいろと情報が揃ってからぼちぼち触ってみようと思っていたけど、ついついちょっとだけってことで。
全然わからんことばかりなので、試しやすそうな疑似乱数 MersenneTwister を錬金してみることにしました。
Alchemyを動かすには、Adobe の Get Start を見ればすんなりといった。amachangさんの「C/C++ のコードを Flash Player で動かす! Alchemy を速攻試してみる。」も非常にわかりやすい。僕の場合は、Windows で Cygwin 環境でしたが同じような感じです。FlexSDK は Gumbo 使ってます。
Mersenne Twister については「Mersenne Twister with improved initialization (2002)」 のソース(mt19937ar.c)を利用しています。
比較する為に用意したクラスは、Onegameさんの記事を参考にさせていただきました。
今回つくったコードとかはこちら。
- mersenne.c (Alchemy用Cソース)
- mersenne.swc (AlchemyででけたSWC)
- MersenneTwister.as (AS3版)
- TestAlchemy.as (テスト用AS)
とりあえず試す
今回は試してみようということで、mt19937ar.c の内、初期化の init_genrand 、乱数生成の genrand_int32 をラップしてASから使えるようにしてみる。
ラップの仕方などAlchemy的な部分は、AlchemyToolkit付属のサンプルや、ドキュメント みながら見よう見まねで。
ここは適当ながら、gccしてみるとswcがでけた。
gcc mersenne.c -swc -o mersenne.swc
さっそくASで使ってみようと。
mxmlc -library-path+=mersenne.swc --target-player=10.0.0 TestAlchemy.as
で、for文で10万回とか回しながら genrand_int32() するテストをAS3版と比較してみる。が、Alchemy版がめっぽう遅い。フリーズしたんかと思った…。どうも呼び出しにはなかなかのコストがかかる模様。
この部分は、TestAlchemy.as の test_alchemy() のところ。mersenne.c では g_int32() です。
C内でArrayつくったらどうか
乱数をひとつひとつ生成するのはあぎゃんな感じだったので、Cの方でActionScriptのArrayをつくったらパフォーマンスでるんでねーかと思ってテストしてみる。Alchemy的には、CでASのクラス生成、ASのメソッド呼び出しなところ。
TestAlchemy.as の test_alchemy_array() のところ。mersenne.c では g_int32_array() です。
結果は前と同じぐらい遅い…。CでASのメソッドを呼ぶのもコストかかってるかと…。ものによるんかも知れんけど。
だったらでByteArrayならどうなの
ArrayがダメならByteArrayってことで、C内でByteArrayに乱数を詰め込んで返すことにしてみる。
TestAlchemy.as の test_alchemy_byteArray() のところ。mersenne.c では g_int32_byteArray() です。
結果は・・・・速くなった!何かうれしい。
TestAlchemyのSWFはこれ(FlashPlayer10必要です)
まとめっぽい何か
今回試してみた印象は、AS←→C 間のやりとりに想像以上にコストかかるらしいってこと。既存のCライブラリを移植していく場合、Cで実装する分、ASに移植する分の案配がパフォーマンスにもろ影響しそう。まだリリースはされてないので今後どうなるかわからんけども。ゆくゆくパフォーマンスのいい OpenCV が使えるようになるとうれしいなぁと。