优化C ++ 11随机生成器的使用

时间:2013-11-20 11:24:45

标签: c++ optimization c++11 random

我正在使用随机数对物理模拟进行大量编码,我只是第一次对我的代码进行了描述,所以我在阅读输出时可能会出错,但我看到这条线先出现了:

   %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name  
 90.09     21.88    21.88   265536     0.08     0.08  std::mersenne_twister_engine<unsigned long, 32ul, 624ul, 397ul, 31ul, 2567483615ul, 11ul, 4294967295ul, 7ul, 2636928640ul, 15ul, 4022730752ul, 18ul, 1812433253ul>::operator()()

这似乎意味着生成数字生成器占用了90%的时间。 我之前已经写过一篇文章,询问如果不在每个循环中构建随机概率分布可以节省我的时间,但在尝试和计时后它没有帮助(Is defining a probability distribution costly?)。是否有优化随机数生成的常用选项?

提前感谢您,我的模拟(在当前状态下)运行了几天,因此减少90%的计算时间将是一个重大进展。

5 个答案:

答案 0 :(得分:4)

在效率,即速度和大小(状态的字节数)与另一方面的任何RNG的“随机性”之间总是存在权衡。梅森捻线机具有相当好的随机性(假设您使用高熵种子,例如std::random_device提供的),但速度慢且具有大状态。 std::minstd_randstd::knuth_b(线性同余)更快且ranlux48(Fibbonacci)更快,但随机性更低(通过较少的随机性测试,即具有一些非随机光谱属性)。如果您对所提供的随机性感到满意(即在随机数据中没有未预料到的相关性),只需进行实验和测试。


编辑: 1 当然,所有这些RNG并非真正随机,并且对于加密也不够随机。如果您需要,请使用std::random_device,但不要抱怨速度。 2 并行(您应该考虑),使用thread_local个RNG,每个RNG用另一个种子初始化。

答案 1 :(得分:3)

如果您的代码花费大部分时间生成随机数,您可能需要花一些时间为您的应用选择最佳算法并自行实现。 Mersenne Twister是一种非常快速的算法,并且具有良好的随机性,但您总是可以权衡生成的随机数的一些质量以获得更高的速度。它取决于您的模拟需求以及您生成的数字类型(整数或浮点数)。如果你绝对需要良好的随机性,Mersenne Twister可能已经是你最好的选择之一。否则,您可能希望在代码中实现简单的linear congruential generator

需要注意的另一件事是,如果你的代码是并行的,你应该使用随机数生成器的可重入版本,并确保不同的线程使用自己的内部状态变量作为它们的生成器。否则,为了避免覆盖生成器的内部状态变量,互斥锁会大大减慢代码的速度。很多图书馆生成器都不是可重入的,请注意。如果您的代码不是并行的,您应该并行化并使用单独的线程填充随机数列表以供模拟使用。另一种选择是使用GPU并行生成随机数。

以下是一些比较不同发电机性能的链接: http://www.boost.org/doc/libs/1_38_0/libs/random/random-performance.html https://www.gnu.org/software/gsl/manual/html_node/Random-Number-Generator-Performance.html

答案 2 :(得分:2)

使用专用的随机数库。

我建议WELL512(链接包含论文和源代码)。

答案 3 :(得分:1)

Marsaglia的KISS RNG速度很快,适合模拟工作。我假设您不需要加密质量。

答案 4 :(得分:1)

如果随机性要求允许,您可以使用RDTSC instruction获取随机数,例如int from0to9 = rdtsc() % 10