繁体   English   中英

使用C ++ 11生成高效的随机数<random>

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM