快速,快速随机整数生成器

时间:2014-12-11 21:15:54

标签: c++ random

像XorShift那样有多种算法可以快速生成满足一般用途的随机数。不幸的是,我需要从[0到10] 生成随机整数,并且在我的代码中使用rand()函数会导致~23%的减速。

问题:从[0到10]生成整数的最快方法是什么?

编辑:基于布兰登评论的信息:

〜23%的减速假设您已将其与某些东西进行了比较。你把它与什么比较了?

>我正在做rand()%10> 5。

此外:

  • 在循环外使用srand(time(0));无效。

  • 隔离的
  • rand() % 10约为19%,因此比较不会对性能造成太大影响。

2 个答案:

答案 0 :(得分:4)

Xorshift是一个很棒的算法。用它来生成一个充满随机位的缓冲区。仅仅因为它一次填充32位缓冲区是没有理由你必须一次从缓冲区读取它们32位。因为你想要速度,你想避免分裂(和mod)。唯一的方法是通过拒绝抽样(也是获得完全无偏的数字的唯一方法)。

由于您只需要11个值(0到10),因此每个样本只需要4位。您将拒绝每16个中的5个,但由于您每32位有8个样本,因此每次Xorshift迭代时平均会有5.5个输出值。

因此,从Xorshift填充一个大缓冲区,然后将该缓冲区转换为(0到10)值,如下所示:

for (int b = 0; b < sizeof inbuf; b += 1) {
    uint8_t v = ((uint8_t *)inbuf)[b];

    if ((v & 0x0F) < 10) { *outbuf++ = v & 0x0F; }
    if (((v >> 4) & 0x0F) < 10) { *outbuf++ = ((v >> 4) & 0x0F; }
}

使outbuf字节数组的大小为inbuf的两倍,并且它大约是11/16满。根据需要重新填充两个缓冲区。

答案 1 :(得分:-1)

您是否尝试过标准的mersenne Twister实施?以下示例来自Microsoft的在线帮助:

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
    uniform_int_distribution<> dist(0,10); // distribute results between 1 and 10 inclusive.

    for (int i = 0; i < 5; ++i) {
        cout << dist(gen) << " "; // pass the generator to the distribution.
    }
    cout << endl;
}

上次我使用了来自Makoto Matsumoto的实施,但速度比rand()快。我没有对它进行基准测试,但我猜测标准实现也更快。

SSE2还对随机数生成提供特殊支持,可能更快:https://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor