【问题标题】:How to generate a massive amount of high quality Random Numbers?如何生成大量高质量的随机数?
【发布时间】:2014-09-26 05:29:00
【问题描述】:

我正在对在晶格中移动的粒子进行随机游走模拟。出于这个原因,我必须创建大量随机数,大约 10^12 及以上。目前我正在使用 C++11 通过<random> 提供的可能性。在分析我的程序时,我发现大部分时间都花在<random> 上。这些数字中的绝大多数都在 0 和 1 之间,分布均匀。在这里,我需要一个来自二项分布的数字。但重点在于 0..1 数字。

问题是:我可以做些什么来减少生成这些数字所需的 CPU 时间以及对它们的质量有何影响?

如您所见,我尝试了不同的引擎,但这对 CPU 时间没有太大影响。另外,我的uniform01(gen)generate_canonical<double,numeric_limits<double>::digits>(gen) 有什么区别呢?

编辑: 通读答案,我得出结论,我的问题没有理想的解决方案。因此,我决定首先让我的程序支持多线程,并在不同的线程中运行多个 RNG(以一个 random_device 编号 + 一个线程单独增量作为种子)。目前这个接缝是最不可避免的步骤(无论如何都需要多线程)。作为进一步的步骤,在等待确切要求时,我考虑切换到建议的英特尔 RNG 或 Thrust。这意味着我的 RNG 实现不应该太复杂,目前不是。但是现在我喜欢关注我的模型的物理正确性,而不是编程的东西,只要我的程序的输出是物理正确的,就会出现这种情况。 Thrust Concerning Intel RNG

这是我目前所做的:

class Generator {
public:
    Generator();
    virtual ~Generator();
    double rand01(); //random number [0,1)
    int binomial(int n, double p); //binomial distribution with n samples with probability p
private:
    std::random_device randev; //seed
    /*Engines*/
    std::mt19937_64 gen;
    //std::mt19937 gen;
    //std::default_random_engine gen;
    /*Distributions*/
    std::uniform_real_distribution<double> uniform01;
    std::binomial_distribution<> binomialdist;
};

Generator::Generator() : randev(), gen(randev()), uniform01(0.,1.), binomial(1,1.) {
}

Generator::~Generator() { }

double Generator::rand01() {
    //return uniform01(gen);
    return generate_canonical<double,numeric_limits<double>::digits>(gen);
}

int Generator::binomialdist(int n, double p) {
    binomial.param(binomial_distribution<>::param_type(n,p));
    return binomial(gen);
}

【问题讨论】:

  • 虽然它不是用 C++ 编写的,但您绝对应该考虑获取一份经过充分审查的 A Million Random Digits with 100,000 Normal Deviates 的副本。我对我的第一本非常满意,所以我买了第二本。
  • @HostileFork:我正在与自己斗争,不给你+1,因为你的评论实际上没有帮助:)
  • 它可能是编译器、操作系统和硬件特定的。在 Linux 上,您至少可以使用 /dev/random 定期为您的 PRNG 播种。然后,您可以选择一个更简单的 PRNG(更快,但更糟),例如 drand48
  • 我确实也是这么想的……因为 1'000'000 个样本还不够;)
  • 您可以有一个辅助文件(带有真实随机数),您可以在其中使用随机数来索引您要使用的文件的哪个块。也许您可以拥有多个索引并将它们之间的块组合在一起 self ,例如 xoring。我不是专家,但如果我没记错的话,异或两个实随机数会给你另一个实随机数。

标签: c++ c++11 random scientific-computing


【解决方案1】:

您可以预处理随机数并在需要时使用它们。

如果您需要真正的随机数,我建议您使用http://www.random.org/ 之类的服务,该服务可确保由环境环境而不是某种算法计算随机数。

而且,谈到随机数,您还必须检查:

【讨论】:

    【解决方案2】:

    如果您需要大量随机数,我的意思是 MASSIVE,请在 Internet 上仔细搜索 IBM 的浮点随机数生成器,该生成器可能在十年前发布。您将不得不购买 PowerPC 机器,或具有融合乘加功能的新 Intel 机器。他们以每个核心每个周期一个的速率获得随机数。因此,如果您购买了一台新的 Mac Pro,您每秒可以实现大约 500 亿个随机数。

    【讨论】:

      【解决方案3】:

      也许您可以使用 GPU 来同时生成多个数字,而不是使用 CPU?

      Efficient Random Number Generation and Application Using CUDA

      【讨论】:

        【解决方案4】:

        在我的 i3 上,以下程序运行大约 5 秒:

        #include <random>
        std::mt19937_64 foo;
        
        double drand() {
          union {
            double d;
            long long l;
          } x;
          x.d = 1.0;
          x.l |= foo() & (1LL<<53)-1;
          return x.d-1;
        }
        
        int main() {
          double d;
          for (int i = 0; i < 1e9; i++)
            d += drand();
          printf("%g\n", d);
        }
        

        而将drand() 调用替换为以下代码会导致程序在大约十秒内运行:

        double drand2() {
          return std::generate_canonical<double,
              std::numeric_limits<double>::digits>(foo);
        }
        

        使用以下而不是drand() 也会导致程序在大约十秒内运行:

        std::uniform_real_distribution<double> uni;
        double drand3() {
          return uni(foo);
        }
        

        也许上面的 hacky drand() 比标准解决方案更适合您的目的..

        【讨论】:

          【解决方案5】:

          任务定义

          OP 要求为这两个问题提供答案

          1.生成速度 -- 假设一组10E+012 随机数是“大量

          2。生成器的质量 -- 假设均匀分布在某个值范围内的数字也是随机的

          但是,对于实际系统,还有更多基本方面需要解决和成功解决:

          A. 定义是否需要为您的系统模拟提供随机数序列的可重复性保证,以便将来重新运行实验.

          如果不是这种情况,模拟实验的重新运行将主要产生不同的结果,那么随机化程序(或预随机化器和随机选择器)无需担心它们的重新运行-进入,状态完整的操作模式,并将获得更简单的实现。

          B. 定义,您需要在什么级别证明生成的随机数的随机性(或者生成的随机数集是否必须属于到一些特定的统计理论定律(一些已知的合成分布或真正随机的随机数集的最大 Kolmogorov 复杂性))。无需成为 NSA 专家就可以说明真随机序列的数值生成器是一个非常困难的问题,并且其计算成本与高随机产品的生产相关。

          超混沌和真随机序列在计算上非常昂贵。对于随机质量敏感的应用程序,使用低随机性或差随机性生成器不是一种选择(无论营销文件怎么说,没有 MIL-STD 或 NSA 分级系统会在环境中尝试这种妥协的质量,结果确实很重要,那么为什么要在科学模拟中满足于更少?如果您不介意错过模拟现象的这么多“未访问”状态,也许这不是问题)。

          C. 验证您的仿真系统需要“每 [usec] 消耗多少个随机数”,以及此设计要求参数是恒定的还是可以通过进入多线程化、矢量化、基于网格/云的分布式计算框架。

          D. 在矢量化或网格/云的情况下,您的模拟系统是否需要维护对随机数池的全局或每个线程或每个网格/云节点的单独访问管理- 基于计算策略。

          任务解决方法

          Fastest [1] 和 best [2] 解决了 [A] 和 [B] 的解决方案,[D] 的选项是预先生成最大随机性将高质量的数字放入足够的访问池中(并在访问策略和访问管理控制上支付可接受的 [C] 和 [D] 成本以从池中重新读取,而不是重新生成)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-06-12
            • 1970-01-01
            • 2015-05-23
            • 2018-02-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多