« NaN の判定 | メイン | 疑似乱数1 »

2015年03月03日

吉里吉里Z 開発:: 2種類の乱数生成メソッド

    

吉里吉里2/Z は、乱数生成メソッドが2種類ある。
Mersenne Twister を使う Math.RandomGenerator クラスと _lrand/rand を使う Math.random メソッド。
シードを指定できるかどうかと乱数の品質からみんな Math.RandomGenerator の方を使って、Math.random を使っている人はいないと思っていたんだけど、どうもそうではない様子。

実際に Math.random を使う理由としては手軽さだろうか?
Math.RandomGenerator のインスタンスを生成する1行の差でしかないと思うが、とりあえず実験やテスト用に動けばいいと言う用途なら Math.random で十分だと思う。
リリースするゲーム等で使用するのに、この1行の差を惜しむことは少ないと思うが、楽なのは間違いない。

速度が速い方が良いと言うことで、Math.random を使っている人もいるだろうか?
速度が理由と言う人は、実際に計測してみたことはあるだろうか?
TJS2 で実際に呼び出して計測してみると、吉里吉里2では10%、吉里吉里Zでは2%ほど、Math.random が速い。
吉里吉里Z の Math.random を XorShift に書き換えてみると 12% 程度になる。
VC の rand が遅いのは、たぶんマルチスレッド用のロック周りの処理があるためではないかと推測される(ソースコードがないので想像)。
bcc については、ソースコードを見るとスレッドごとに状態を持つ実装になっているので、比較的オーバーヘッドが少ないのであろう。
この程度の差のために Math.random を使っているのだろうか?
実際の計測は、以下のようなスクリプトの実行時間を System.getTickCount で挟んで計った。

var m = Math;
for( var i = 0; i < 1000000; i++ ) {
 sum += m.random();
}

Math.random() と呼び出していないのは、そのように記述するとだいぶ遅くなるから。
以下のように記述した Math.RandomGenerator を使用するスクリプトの1.5倍以上遅い(2とZで30%程度差は異なる)。

var rng = new Math.RandomGenerator(0);
for( var i = 0; i < 1000000; i++ ) {
 sum += rng.random();
}

Math.random() と書いて何度も呼び出していたら、速いから使うと言う理由は完全になくなる(逆に遅くなっている)。
Math.RandomGenerator をクラスメンバに持って呼び出したとしても、Math.random() と呼び出す方が遅い。

つまり、TJS2 スクリプトとして実行する上では、無視できるくらいの速度差でしかないことになる。


投稿者 Takenori : 2015年03月03日 18:22




comments powered by Disqus
Total : Today : Yesterday : なかのひと