C++11の乱数生成器 (random number generator; RNG) である<random>はとてもよくできている。 single threadで動くプログラムなら自作の珍妙なラッパを介さず直接使うべき。 thread safeなのでOpenMPからも使うことができる。 高速にかつ2カ所以上でRNGを使うことを前提にして、 ここgistに自作の珍妙なラッパを公開してみる。
thread数ぶん作った乱数生成エンジンを2カ所 (main.cpp と timing.h) で使う。
- 乱数生成エンジンを thread local storage (TLS) として確保し、externで大域変数とする。
- std::uniform_real_distribution<double> は乱数生成エンジンを引数にとって、所望の精度(ここではdouble)の一様分布乱数を返す。 これもスレッド毎に確保するが、大域変数とはしない。
- 内部でstd::generate_canonicalを通している。 所望の精度(ここではdouble)に達するまで乱数生成エンジン (32 or 64 bit) が必要な回数だけ繰り返し呼び出される。
- doubleの一様分布乱数が欲しい場合は32 bitより64 bitの乱数生成エンジンを用いるほうが高速といわれている。
- 2012年頃発売の2.5 GHz Intel Core i5で、倍精度なら約50M個/秒/core。
- 2018年頃発売のIntel Xeonで、倍精度なら約100M個/秒/core、単精度なら約300M個/秒/core。
- Hyper Threadingは乱数の発生だけならわりと有効に機能するが、たいていの場合において乱数を使う他の計算で十分には機能しない。
- <random>はもともとBoostの一部として開発されC++11の一部として取り込まれたので、Boostにもほぼ同じ擬似乱数生成器がある。 g++のversion 4か5まではBoostの生成器のほうが高速だった。g++ version 7以降はほぼ変わらない生成速度になっている。
(書きかけ)
- 1-r
- std::uniform_real_distributionの引数で
- Boostには球面