我正在尝试在我的TSP生成器上进行一些opt-3交换以获得欧几里德距离,并且由于我在很多情况下有超过500个节点,我需要随机选择我想要的3个节点中的至少1个尝试交换。
所以基本上我需要一个快速的随机数函数。 (正常的rand()太慢了)它不一定非常棒,只需要足够。
编辑: 我忘了提一下,我坐在一个我无法添加任何库的环境中,除了标准语言库(例如STL,iostream等)。所以没有boost = /
答案 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的处理器(几乎全部都是),并且更复杂。
答案 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)
即使这篇文章已经有好几年了,但是当我找到一个类似的答案时,它就出现了,而我最后使用的答案,甚至还没有。所以我添加了我找到的那个;
这种方法将构建一个自包含的随机生成器,我发现它比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之间的数字。