[英]Efficient random number generation with C++11 <random>
我试图了解如何使用C ++ 11随机数生成功能。 我担心的是表现。
假设我们需要在0..k
之间生成一系列随机整数,但k
在每一步都会发生变化。 什么是最好的方法?
例:
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
std::uniform_int_distribution<> dist(0, k);
int random_number = dist(engine);
// do something with random number
}
<random>
标头提供的分发非常方便。 但它们对用户来说是不透明的,因此我无法轻易预测它们的表现。 例如,不清楚上面构造的dist
会导致多少(如果有的话)运行时开销。
相反,我可以使用类似的东西
std::uniform_real_distribution<> dist(0.0, 1.0);
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
int random_number = std::floor( (k+1)*dist(engine) );
// do something with random number
}
这避免了在每次迭代中构造一个新对象。
随机数通常用于性能很重要的数值模拟中。 在这些情况下使用<random>
的最佳方法是什么?
请不要回答“简介”。 分析是有效优化的一部分,但是对如何使用库以及该库的性能特征有很好的理解。 如果答案是它依赖于标准库实现,或者知道的唯一方法是对其进行分析,那么我宁愿不使用<random>
的分发。 相反,我可以使用我自己的实现,这对我来说是透明的,并且在必要时更容易优化。
你可以做的一件事就是拥有一个永久的分发对象,这样你每次只能创建一个param_type
对象:
template<typename Integral>
Integral randint(Integral min, Integral max)
{
using param_type =
typename std::uniform_int_distribution<Integral>::param_type;
// only create these once (per thread)
thread_local static std::mt19937 eng {std::random_device{}()};
thread_local static std::uniform_int_distribution<Integral> dist;
// presumably a param_type is cheaper than a uniform_int_distribution
return dist(eng, param_type{min, max});
}
为了最大化性能,首先要考虑不同的PRNG,例如xorshift128 + 。 据报道,对于64位随机数,它的速度是mt19937
两倍多; 见http://xorshift.di.unimi.it/ 。 它可以用几行代码实现。
此外,如果你不需要“完全平衡”的均匀分布,并且你的k
远小于2^64
(可能是),我建议只写一些东西:
uint64_t temp = engine_64(); // generates 0 <= temp < 2^64
int random_number = temp % (k + 1); // crop temp to 0,...,k
但请注意,整数除法/模运算并不便宜。 例如,在Intel Haswell处理器上,64位数字需要39-103个处理器周期,这可能比调用MT19937或xorshift +引擎要长得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.