疑似乱数の計算時間

お久しぶりです.
実に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の間には明確な差があるっぽいです.