乱数生成について・・xorshiftすげぇ
モンテカルロ法で計算するときには、乱数の質についての話題がよく出てきます。
乱数に偏りがあると、正確な推定ができなくなるためです。
で、C言語標準のrand関数はあまり乱数の質が良くなくて、サンプリングする方向に偏りができてしまうとのことです。
そこで、別の乱数生成法を用いるのですが、レンダラ関係ではメルセンヌツイスタがよく用いられています。
が、今回はコチラ↓の記事で見かけたxorshift法というのを試してみました。
http://lucille.atso-net.jp/wiki/index.php?%CD%F0%BF%F4
xorshift法はxorとシフト演算のみで超高速に疑似乱数を生成するものです。
パストレなどでは、ロシアンルーレットで反射方向を決める際など、多くの場所で乱数を生成する必要があります。なので、xorshiftを用いることで高速化ができないかな、と思いxorshiftがどの程度早いのか実際に試してみました。
(まだレンダラに組み込んではいませんが・・)
ちなみにxorshiftによる乱数生成ルーチンはたったコレだけ。
unsigned long xor128(){ static unsigned long x=123456789,y=362436069,z=521288629,w=88675123; unsigned long t; t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) ); }
このルーチンとC言語標準のrand関数それぞれで、1億回乱数を生成する時間を比較してみました。
関数 | デバッグ | リリース |
---|---|---|
rand() | 4.078秒 | 3.5秒 |
xor128() | 5.359秒 | 0.25秒 |
最初、デバッグモードで比較したところ、rand関数の方が速くてアレ??と思ったのですが、xorshift法はリリースモードにすると一気に速くなります。
xorとシフト演算は最適化がうまく働くってことなのかな。