几个随机数c ++

时间:2014-12-01 18:02:56

标签: c++ c++11 random prng

我是一名物理学家,编写的程序涉及从高斯分布中生成几个(数十亿的数量级)随机数。我正在尝试使用C ++ 11。这些随机数的生成由一个应该花费很少时间的操作分开。我最担心的是,如果我生成如此多的随机数,并且时间间隔很小,则可能导致性能欠佳。我正在测试某些统计属性,这些属性严重依赖于数字随机性的独立性,因此,我的结果对这些问题特别敏感。我的问题是,我在下面的代码中提到的数字类型(我的实际代码的简化版本),我做的事情显然(甚至是巧妙的)错误吗?

#include <random>

// Several other includes, etc.

int main () {

  int dim_vec(400), nStats(1e8);
  vector<double> vec1(dim_vec), vec2(dim_vec);

  // Initialize the above vectors, which are order 1 numbers.

  random_device rd;
  mt19937 generator(rd());
  double y(0.0);
  double l(0.0);

  for (int i(0);i<nStats;i++)
    {
      for (int j(0);j<dim_vec;j++)
        {
          normal_distribution<double> distribution(0.0,1/sqrt(vec1[j]));
          l=distribution(generator);
          y+=l*vec2[j];
        }
      cout << y << endl;
      y=0.0;
    }
}

2 个答案:

答案 0 :(得分:6)

允许normal_distribution拥有州。并且通过这种特定的分布,通常与每个其他调用成对地生成数字,并且在奇数调用上,返回第二个缓存的数字。通过在每次调用中构建新的分发,您将丢弃该缓存。

幸运的是,你可以&#34;塑造&#34;通过使用不同的normal_distribution :: param_type&#39; s来调用单个分布:

 normal_distribution<double> distribution;
 using P = normal_distribution<double>::param_type;
 for (int i(0);i<nStats;i++)
    {
      for (int j(0);j<dim_vec;j++)
        {
          l=distribution(generator, P(0.0,1/sqrt(vec1[j])));
          y+=l*vec2[j];
        }
      cout << y << endl;
      y=0.0;
    }

我不熟悉std::normal_distribution的所有实现。但是我为libc++写了一个。所以我可以肯定地告诉你,我对你的代码的轻微改写将产生积极的性能影响。我不确定它会对质量产生什么影响,只是说我知道它不会降低质量。

<强>更新

关于Severin Pappadeux下面关于在分布中一次生成数字对的合法性的评论:请参阅N1452讨论并允许这种技术的地方:

  

分布有时会存储来自其相关来源的值   调用其运算符的随机数()。例如,一个常见的   生成正态分布随机数的方法是   检索两个均匀分布的随机数并计算两个   正常分布的随机数。为了重置   分发的随机数缓存到定义的状态,每个   发行版具有重置成员功能。应该在a上调用它   交换或恢复相关引擎时的分配。

答案 1 :(得分:1)

关于优秀HH回答的一些想法

  1. 正态分布(mu,sigma)由正常(0,1)按班次和比例生成:
  2. N(μ,sigma)= mu + N(0,1)* sigma

    如果您的平均值(mu)始终为零,则可以通过执行类似

    之类的操作来简化和加速(通过不添加0.0)代码
    normal_distribution<double> distribution;
    for (int i(0);i<nStats;i++)
    {
      for (int j(0);j<dim_vec;j++)
        {
          l  = distribution(generator);
          y += l*vec2[j]/sqrt(vec1[j]);
        }
      cout << y << endl;
      y=0.0;
    }
    
    1. 如果速度至关重要,我会尝试预先计算主要10 ^ 8循环之外的所有内容。是否可以预先计算sqrt(vec1 [j]),以便节省sqrt()调用?是否有可能 将vec2 [j] / sqrt(vec1 [j])作为单个向量?

    2. 如果无法预先计算这些向量,我会尝试节省内存访问。保持vec2 [j]和vec1 [j]的各个部分可能有助于获取一个缓存行而不是两个。因此,请声明vector<pair<double,double>> vec12(dim_vec);并在抽样y+=l*vec12[j].first/sqrt(vec12[j].second)

    3. 中使用