最佳伪随机数发生器

时间:2011-01-18 05:40:26

标签: random

截至今天哪个是最好的伪随机数发生器?最好的 我的意思是 -

  1. 通过所有统计测试
  2. 即使在非常高的尺寸下也表现良好
  3. 有一个非常大的时期
  4. 我能想到MT。有没有比MT好的PRNG? MT的哪种变体最好?

7 个答案:

答案 0 :(得分:30)

只是一个快速的更新,因为答案显示他们的年龄:今天Mersenne Twister不再被认为是最先进的技术(有点臃肿,可预测只有624个值,播种速度慢,播种能力差,......)

正常PRNG

对于正常应用,需要良好的统计特性和速度,请考虑

  • O' Neill的PCG family
  • Vigna的xoroshiro family,比如xoroshiro128 +(不是日本名字顺便说一句,但是" X-或者,旋转,移动,旋转")。

密码安全PRNG(CSPRNG)

对于非可预测性非常重要的加密应用程序,请考虑使用加密安全的PRNG,例如

  • 伯恩斯坦ChaCha20RFC 7539。替代方案是
  • 吴的HC-256,
  • 詹金斯的ISAAC64
  • d。 E. Shaw的Random123套件(包括名称很好的ARS,简化了用AES-CTR加密无限的零序列), 虽然我不确定他们的审查程度如何。

PRNG测试

同样,对于PRNG的统计测试,现在最先进的技术可能是

  • L' Ecuyer的TestU01(使用SmallCrush,Crush,BigCrush),
  • Doty-Humphrey的pracrand及其PractRand套件,

虽然这些在历史上很重要,但过时了:

  • Marsaglia' DieHard,DieHarder,
  • NIST 800-22 A。

答案 1 :(得分:20)

尝试MT的继任者:SFMT(http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html)。首字母缩略词代表面向SIMD的Fast Mersenne Twister 。 它使用向量指令,  像SSE或AltiVec,以加快随机数生成。

此外,它显示的周期比原始MT更长:SFMT可以配置为使用最多2 216091 -1的周期。

最后,MT在初始化时遇到了一些问题:它倾向于抽取大量的0,导致质量差的随机数。在通过算法的重现进行补偿之前,此问题可能持续多达700000次绘制。因此,SFMT也被设计为比这个过剩更快地离开这个零过剩状态。

检查我在本文开头给出的链接,找到源代码和描述该算法的科学出版物。

为了说服你,你可以在这里看http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/speed.html一张比较MT和SFMT发电速度的表格。无论如何,SFMT在提供比MT更好的品质的同时更快。

- 编辑以下评论 -

更一般地说,当您选择PRNG时,您需要考虑您正在开发的应用程序。实际上,一些PRNG更适合某些应用程序约束。例如,MT和WELL生成器不适合加密应用程序,而它们是处理蒙特卡罗模拟时的最佳选择。

在我们的案例中,由于其比SFMT具有更好的等分布特性,WELL可能看起来很理想。尽管如此,WELL也慢得多,而且他无法显示像SFMT那样大的时段。

作为结论,PRNG不能被声明为所有应用程序的最佳选择,而是适用于特定域名,特别是具有特定情况的应用程序。

答案 2 :(得分:5)

如果您查找的算法通过了所有统计测试,但仍然很快,您可以尝试Xorshift-Algorithm。与Java中的随机库相比,它的速度提高了约30%,并提供了更好的结果。它的时期不像Mersenne Twister那么长,但它仍然不错。

可以在此处找到实施:

http://demesos.blogspot.com/2011/09/replacing-java-random-generator.html

修改

似乎XORShift的新变种现在甚至在质量上击败了MerseneTwister和WELL(尽管不是时期)。他们通过了更多的经验质量测试,如PRNG Shootout中所示。

他们的表现也令人印象深刻。 我在这里做了Java,源和结果的不同实现的基准测试: https://github.com/tobijdc/PRNG-Performance

答案 3 :(得分:4)

嗯,WELL generator是对MT-19937的概括和改进。

答案 4 :(得分:4)

  
      
  1. 通过所有统计测试
  2.   

到目前为止,其他答复中提到的每个PRNG都属于GFSR / LFSR PRNG系列。所有这些都失败了二进制矩阵秩和可能线性复杂性测试。

有许多PRNG通过所有通用统计测试,但由于某些原因,人们似乎发现GFSR更性感。

以下是通过所有通用统计测试的示例PRNG,但不具有加密安全性:

static unsigned long long rng_a, rng_b, rng_c, rng_counter;
unsigned long long rng64() {
    unsigned long long tmp = rng_a + rng_b + rng_counter++;
    rng_a = rng_b ^ (rng_b >> 12);
    rng_b = rng_c + (rng_c << 3);
    rng_c = ((rng_c << 25) | (rng_c >> (64-25))) + tmp;
    return tmp;
}
void seed(unsigned long long s) {
    rng_a = rng_b = rng_c = s; rng_counter = 1;
    for (int i = 0; i < 12; i++) rng64();
}

(假设long long是64位整数类型......我认为在为该类型定义的每个地方都是如此?)

这对于任何正常使用都是足够的,并且相当快。如果您需要更好的东西,请切换到CSPRNG - 它们往往比任何非加密PRNG好得多。例如,ChaCha(http://cr.yp.to/chacha.html)是一个坚固的CSPRNG,具有快速播种,随机访问和可调节的质量。 HC-256(http://en.wikipedia.org/wiki/HC-256)是一种质量更高的CSPRNG,播种速度慢,但播种后速度相当快。

  
      
  1. 即使在非常高的尺寸下也表现良好
  2.   

这几乎相当于第一点。此外,我提供的示例PRNG是混乱类型 - 这样的PRNG,当它们行为不端时,在少量维度而不是大数量的情况下这样做。

  
      
  1. 有一个非常大的时期
  2.   

定义极大?

上面提供的示例PRNG I具有可证明的最小周期2 ^ 64并且平均周期为2 ^ 255并且状态空间为2 ^ 256。对于我链接的两个CSPRNG,ChaCha的周期为2 ^ 68,状态空间为2 ^ 260,而HC-256的平均周期大约为2 ^ 65000左右,并提供了一个概率证明其最短周期长于2 ^ 128,可能性大于1-(2 ^ -128),并且它具有大约2 ^ 65000的状态空间。

在实践中,时间无关紧要大约2 ^ 60,甚至那是微不足道的。通常人们要求高时期的原因是因为要么他们不知道他们在谈论什么,要么因为他们需要一个大的状态空间(至少等于周期,但通常更大),这可能是有益的到2 ^ 250左右。但是一个大的状态空间并没有多大帮助,除非你从大于单个整数的东西中播种,大多数人都没有。

(注意:在代码中,^用于表示xor,但在文本中^用于表示指数)

答案 5 :(得分:2)

MT似乎超出了你的标准:

  

它具有2 19937 -1次迭代(> 43×10 6,000 )的巨大周期,被证明在(最多)623维度中等分(对于32位值),并且比其他统计上合理的生成器运行得更快

From: Wikipedia

  

Mersenne Twister是现存最广泛测试的随机数发生器之一。但是,它完全是确定性的,并不适用于所有目的,并且完全不适合加密目的。

From: Python docs

wikipedia有一些关于加密安全prng的说法,如果那是你的兴趣。

答案 6 :(得分:0)

除了Mersene Twister及其变体之外,您还可以使用Salsa20及其变体(Chacha等)。