疑似乱数の計算時間
お久しぶりです.
実に1年と2ヶ月2週間ぶりの更新です.
リアルが忙しいという事もあったと言えばあったのですが,趣味のプログラミングに労力を割く気力がなかったといいますか,つまり五月病みたいなものですね….
まあそんなネガティブな話はもう忘れてしまって,これからはちょいちょい更新していきたいと思います.
疑似乱数
さて,今回は疑似乱数のお話です.
代表的な疑似乱数生成方法としては,以下のようなものがあります.
標準のCでは,線形合同法のrand()が用意されています.
でもこれはあんまり賢くない方法なので,大事なシミュレーションとかでは使わない方がいいみたいです.
とりあえずメルセンヌ・ツイスタを使っておけば間違いないようです.
疑似乱数生成器の速度比較
今回は,疑似乱数生成器の計算速度の比較をします.
実行環境は,こんな感じ.
CPU | Intel Core i7 2700K@3.5GHz |
---|---|
OS | Ubuntu 12.04 32bit |
gcc | 4.6.3 |
コンパイラオプションは,最適化とSSE2を使用する形で.
と言っても,SSE2を使うのは後述のsfmtだけです.
-O3 -msse2 -DHAVE_SSE2=1 -DSFMT_MEXP=19937
疑似乱数一覧
省略名 | 詳細 | 周期 |
---|---|---|
std | C標準のrand関数 | 2^31-1 |
mt | Mersenne Twister | 2^19937-1 |
sfmt | SIMD-oriented Fast Mersenne Twister | 2^19937-1 |
boost | boostのMersenne Twister | 2^19937-1 |
xor | Xorshift | 2^128-1 |
mseq | M系列乱数 | 2^521-1 |
結果
1億回乱数発生させたforループ全体の時間を計測しました.
結果は以下の通り.
乱数 | 1回分の時間 | 1秒あたり回数 | stdとの比較 |
---|---|---|---|
std | 1.08e-09 | 9.26e+07 | 1.000 |
mt | 4.44e-09 | 2.25e+08 | 0.411 |
sfmt | 1.08e-09 | 9.29e+08 | 0.100 |
boost | 2.16e-09 | 4.63e+08 | 0.200 |
xor | 1.55e-09 | 6.47e+08 | 0.143 |
mseq | 1.60e-09 | 6.26e+08 | 0.148 |
速度の早い順に並べると,次のようになります.
sfmt > xor > mseq > boost > mt > std
SSEとか使える環境ならやっぱりSFMTが速いようです.
環境に依存しない方法なら,XorshiftやM系列乱数がMersenne Twisterよりも速いということになります.
SSEすごいな.
あと,なんでboostよりmtが遅いんでしょう.
生成された乱数列を見る限り,boostとmtは全く同じものを生成しているはずなのですが.
boostさんがちょっと工夫してるんでしょうか….
(3月26日追記)
補足ですが,1億回のループを10回やって平均をとっています.
分散も,計測値:偏差=1:10^-3くらいなので,,boostとmtの間には明確な差があるっぽいです.