我能找到的大多数随机函数是一个序列函数,它将最后生成的结果保留为下一个调用的种子
我想要一个可以单独运行的纯函数,并且可以给定看似随机的序列(从头到尾任意数量)和种子
说实话,我希望算法仅在开始时使用随机种子并将每个元素的索引作为输入,才能并行生成随机数(并且可以在GPU中使用)
也许我可以使用哈希函数,但是我想知道哪种算法可以提供最可能的均匀分布,并且在给定任何种子和任何长度的情况下,看起来总是随机的
edit:谢谢您的所有建议。我对自己想要的东西有一个更扎实的想法
我不需要很多雪崩特性,但是我更关心均匀分布。而且要使其平行,它必须是无状态算法,因此大多数PRNG都不适合
但最不用担心的是安全性。我希望通过人类感知来获得一个看似随机的序列,但不要将其用于任何安全性,仅用于视觉和界面
如果算法非常快,将不胜感激
答案 0 :(得分:2)
“纯”随机函数有几种选择。其中包括:
另请参阅我的article on designs for PRNGs或L'Ecuyer,Munger等人的文章“并行计算机的随机数:要求和方法,重点放在GPU上”(2015年)。
对于要使用的hash functions,有多种选择,包括SHA-1,SHA-256,xxHash,MurmurHash3等。取决于您是否需要安全性以及其他因素,某些哈希函数可能比其他哈希函数更合适。
大多数散列函数输出一个位序列,但是不难看出如何将它们转换为数字-例如,请参见this question或我的article on numbers bounded by 0 and 1。
答案 1 :(得分:1)
好的,这是关于这个问题的一些想法。
伪随机函数通常称为伪随机数生成器(PRNG)。
您可能会对[0 ... 1]范围内的双精度感兴趣,但是PRNG通常会生成单个64位(适合双精度)或32位(适合浮点)整数。转换为两倍,虽然不是很琐碎,但相当simple operation。
典型的PRNG具有状态(由种子启动)和输出。对于最简单的PRNG(例如LCG)种子,状态和输出是同一回事,但通常情况并非如此。通常,状态的特征在于位数(例如,LCG为64位,梅森绞线为19937位)。
使用任何PRNG算法制作纯函数都非常简单-PRNG只是三个函数的集合,形式为
state_type make_state(seed_type seed) {
// convert seeding to state, bits chopping
return new_state;
}
state_type advance_state(state_type old_state) {
// do bits chopping with old state
// and advance to the next state
return new_state;
}
uint64_t generate_output(state_type state) {
// extract 64bits of randomness from state
return new_random_number;
}
就是这样,PRNG中除了这些功能外没有其他内容。
还有,要解决的问题
您可以使用具有良好Avalanche properties的非加密哈希,这基本上意味着输入值的单个位更改(输入增加1)会导致输出大变化。快速,合理,可能不是很随机。 Murmur以及Mum hash都可以。
以计数器模式运行的加密密码。比选项1慢,但质量较高。相对大状态(例如512位左右)。我更喜欢ChaCha20-它众所周知,速度很快,请看代码here。选项1和2都假定您只是线性增加计数器作为输入。
另一个选择是使用PRNG,它具有对数复杂度超前功能。您可以从全局种子开始,如果您有2 10 CUDA内核,则第一个内核将使用种子,第二个内核将以2 64 / 2 向前跳10 = 2 54 ,其中复杂度为O(log 2 (N))的操作只有54次,第三个将比第二个多2个> 54 步骤和54操作等等。在已知的PRNG中,对数跃迁适用于LCG和PCG。我建议看一下PCG。
这意味着存在非平凡功能,形式为
state_type advance_state(state_type old_state, int64_t distance) {
// non-trivial advance by distance
// non-trivial means it is not just a loop, it is better than linear algorithm
return new_state;
}