C ++快速正常随机数发生器

时间:2015-11-19 13:02:46

标签: c++ random normal-distribution

我正在使用mt19937生成器生成正常的随机数,如下所示:

normal_distribution<double> normalDistr(0, 1);    
mt19937 generator(123);
vector<double> randNums(1000000);
for (size_t i = 0; i != 1000000; ++i)
{
    randNums[i] = normalDistr(generator);
}

上面的代码可行,但由于我在代码中生成了超过1亿个普通随机数,因此上述代码非常慢。

是否有更快的方法来生成正常的随机数?

以下是有关如何使用代码的一些背景知识:

  • 随机数的质量并不重要
  • 数字的精确度并不重要,doublefloat都可以
  • 正态分布总是具有mean = 0和sigma = 1

修改

@Dúthomhas,Andrew:

分析后,以下功能占用的时间超过50%:

std::normal_distribution<double>::_Eval<std::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433‌​253> >

3 个答案:

答案 0 :(得分:3)

最重要的是,你真的需要100,000,000个随机数同时吗?从RAM写入和随后读取所有这些数据不可避免地需要大量时间。如果你一次只需要一个随机数,你应该避免这种情况。

假设你确实需要RAM中的所有这些数字,那么你应该首先 如果您真的想知道CPU时间花费/丢失的位置,请编写代码。

其次,您应该避免不必要的重新分配和数据初始化。通过将std::vector::reserve(final_size)std::vector::push_back()结合使用,可以轻松完成此操作。

第三,你可以使用比std::mt19937更快的RNG。当数字的质量很重要时,建议使用RNG。 online documentation表示lagged Fibonacci generator(在std:: subtract_with_carry_engine中实现)速度很快,但可能没有足够长的重复周期 - 您必须检查这一点。或者,您可能希望使用std::min_stdrand(使用linear congruential generator

std::vector<double> make_normal_random(std::size_t number,
                                       std::uint_fast32_t seed)
{
  std::normal_distribution<double> normalDistr(0,1);    
  std::min_stdrand generator(seed);
  std::vector<double> randNums;
  randNums.reserve(number);
  while(number--)
    randNums.push_back(normalDistr(generator));
  return randNums;
}

答案 1 :(得分:2)

您还需要查看std :: vector reserve而不是调整大小。它将允许您获得1次拍摄所需的所有记忆。我假设你不需要一次全部1亿双打?

答案 2 :(得分:0)

如果确实是生成器导致性能下降,那么使用普通的rand函数(需要成对绘制数字),转换为浮点数或在0,1中加倍,然后应用Box Muller变换。

这在时间上很难被击败,但请注意统计属性并不比兰特好。

数字食谱例程gasdev这样做 - 您应该能够下载副本。