像XorShift那样有多种算法可以快速生成满足一般用途的随机数。不幸的是,我需要从[0到10] 生成随机整数,并且在我的代码中使用rand()
函数会导致~23%的减速。
问题:从[0到10]生成整数的最快方法是什么?
编辑:基于布兰登评论的信息:
〜23%的减速假设您已将其与某些东西进行了比较。你把它与什么比较了?
>我正在做rand()%10> 5。
此外:
在循环外使用srand(time(0));
无效。
rand() % 10
约为19%,因此比较不会对性能造成太大影响。
答案 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