需要c ++的快速随机生成器[关闭]

问题描述 投票:45回答:10

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

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

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

c++ random performance
10个回答
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矩阵,它开始产生太少或太多的奇异矩阵(我忘了哪个)。已经证明,该发生器相当于线性移位反馈寄存器。但除非你正在进行密码学或严肃的蒙特卡罗工作,否则这台发电机会晃动。


0
投票

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


28
投票

来自intel网站的两个不错的选择:

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/


12
投票

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


6
投票

Mersenne Twister有一些快速实现。


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

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);

1
投票

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

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

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


1
投票

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

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


0
投票

你能提前预先生成一堆随机位并一次剥掉它们(因为你只需要1到3之间的随机数)吗?

© www.soinside.com 2019 - 2024. All rights reserved.