【发布时间】: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