需要一个用于c ++的快速随机生成器

时间:2009-10-28 21:33:34

标签: c++ random performance

我正在尝试在我的TSP生成器上进行一些opt-3交换以获得欧几里德距离,并且由于我在很多情况下有超过500个节点,我需要随机选择我想要的3个节点中的至少1个尝试交换。

所以基本上我需要一个快速的随机数函数。 (正常的rand()太慢了)它不一定非常棒,只需要足够

编辑: 我忘了提一下,我坐在一个我无法添加任何库的环境中,除了标准语言库(例如STL,iostream等)。所以没有boost = /

10 个答案:

答案 0 :(得分:62)

另一个帖子提到了Marsaglia的xorshf生成器,但没有人发布代码。

static unsigned long x=123456789, y=362436069, z=521288629;

unsigned long xorshf96(void) {          //period 2^96-1
unsigned long t;
    x ^= x << 16;
    x ^= x >> 5;
    x ^= x << 1;

   t = x;
   x = y;
   y = z;
   z = t ^ x ^ y;

  return z;
}

我到处都使用过这个。它失败的唯一地方是我试图生成随机二进制矩阵。过去大约95x95矩阵,它开始产生太少或太多的奇异矩阵(我忘了哪个)。已经证明,该发生器相当于线性移位反馈寄存器。但除非你正在进行密码学或严肃的蒙特卡罗工作,否则这个发生器会摇摆不定。

答案 1 :(得分:28)

来自英特尔网站的两个不错的选择:

1)fastrand - 它比std rand()快2.01 X.例程返回一个整数,类似于C lib的输出值范围。

inline int fastrand() { 
  g_seed = (214013*g_seed+2531011); 
  return (g_seed>>16)&0x7FFF; 
} 

2)SSE版本(参见下面的链接)与std rand()的速度大约是5.5 X,但是它一次生成4个随机值,需要一个带有sse的处理器(几乎全部都是),并且更复杂。

http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/

答案 2 :(得分:12)

请参阅随机数发生器专家George Marsaglia的these generators。它们被实现为C宏,它们闪电般快速,每个数字生成一些操作。

答案 3 :(得分:6)

Mersenne Twister有一些快速实现。

答案 4 :(得分:6)

Ivy Bridge架构开始,英特尔添加了RdRand CPU指令,AMD于2015年6月晚些时候添加了它。因此,如果您的目标处理器是新的,并且不介意使用(内联) )汇编,生成随机数的最快方法应该是调用RdRand CPU指令来获得16位或32位或64位随机数,如here所述。滚动到大约页面中间以获取代码示例。在该链接上还有一个代码示例,用于检查当前CPU是否支持RdRand指令,另请参阅Wikipedia以获取有关如何使用CPUID指令执行此操作的说明。

相关问题:Making use of sandy bridge's hardware true random number generator?(虽然根据维基百科,RdRand指令首先出现在Ivy Bridge中,但不是Sandy Bridge架构,因为该问题说明了)

基于_rdrand64_step()的示例C ++代码:

#include <immintrin.h>

uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
  // Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number

答案 5 :(得分:2)

即使这篇文章已经有好几年了,但是当我找到一个类似的答案时,它就出现了,而我最后使用的答案,甚至还没有。所以我添加了我找到的那个;

#include <random> msdn entry

这种方法将构建一个自包含的随机生成器,我发现它比rand()%x更随机;超过几十万次迭代。 rand()%永远不会连续抛出16个以上的头/尾,当它每隔65k次尝试时。这个不仅如此,而且它在四分之一的时间内完成。

这就是我自己实施#include <random>的方式:

//create rng_gen, using mt technique, with range 0,1 (coin) and 1,6(dice);
std::random_device rd; //seed
std::mt19937 gen(rd()); //seed for rd(Mersenne twister)
std::uniform_int_distribution<> rng_coin(0, 1); //rng1 range
std::uniform_int_distribution<> rng_dice(1, 6); ///rng2 range

rng_coin(gen); //will apply rng1 range on (gen) object. Is very fast
rng_dice(gen); //will apply rng2 range, returns int.

//will output 1000 cointosses to console
for (int i=0;i<1000;++i)std::cout<<rng_coin(gen)<<"\n";
//will generate 1000 dice throws
for (int i=0;i<1000;++i)rng_dice(gen);

答案 6 :(得分:1)

Boost库有一组随机生成器。可以找到绩效图表here

编辑:在原始问题编辑之前,这个答案就在这里。但我希望它仍然有用,所以我把它放在这里。

答案 7 :(得分:1)

rand()真的很快,我不相信你会发现更快。

如果它实际上减慢了你的速度(我有点怀疑),那么你需要改变架构。

我建议使用随机数预填充长列表,然后在需要时,只需从列表中选择一个,而不是生成一个。您可以使用后台线程重新填充列表。

答案 8 :(得分:0)

你可以提前预先生成一堆随机位并一次剥离2个(因为你只需要1到3之间的随机数)吗?

答案 9 :(得分:0)

我认为WELL相当不错,WELL512a很短。 http://www.iro.umontreal.ca/~panneton/WELLRNG.html WELL44497a在当时也很复杂。但是,WELL会生成0到1之间的数字。