为什么 rand() 比 arc4random() 快得多?

Why is rand() much faster than arc4random()?

我正在编写一个需要快速生成整数随机数的游戏 AI。这个游戏是MacOS,所以有两个选择rand()(普通C)和arc4random()(BSD)。我没有发现这两个函数在速度上有什么可比性,所以我写了一个小程序来测试一下:

long i;

// Record timestamp here.
srand((unsigned int)time(NULL));
for (i = 0; i < 999999999; ++i) {
    rand();
}
// Record timestamp here.
for (i = 0; i < 999999999; ++i) {
    arc4random();
}
// Record timestamp here and print all three.

我测试了好几次。结果非常稳定:srand()rand() 的 999999999 次迭代大约需要 6 秒,而 arc4random() 需要更长的时间(大约 30 秒)。

arc4random() 需要更长的时间有什么原因吗?或者我的测试有什么缺陷。谢谢!

你的结果是合理的。

这两个函数是为不同的目的而设计的,它们基于完全不同的class伪随机数生成器。

rand() 是一个 pseudorandom number generator (PRNG), generally implemented as a linear congruential generator (LCG),速度相当快,但通常它的统计特性非常糟糕。

arc4random() 是一个 cryptographically secure pseudorandom number generator (CSPRNG), which is generally slower but also suitable for cryptographical use, which implies it has higher statistical quality of randomness than a PRNG. According to the documentations here, here and here:

The function when originally implemented in OpenBSD, used the RC4 cipher to produce the output stream. OpenBSD now uses a ChaCha20 stream cipher.

RC4 has been designed by RSA Data Security, Inc. It was posted anonymously to the USENET and was confirmed to be equivalent by several sources who had access to the original cipher. Since RC4 used to be a trade secret, the cipher is now referred to as ARC4.


了解这两个 class 伪随机数生成器之间的区别很重要。

A PRNG 专为您所关心的(理想情况下)大量统计随机性而设计:您想要模拟随机性的字段。

A CSPRNG 设计用于后者根本不够的目的,但还需要大量的不可预测性(即使生成器算法完全已知):字段密码学。

因此您不需要 CSPRNG 来生成具有高质量统计随机性的数字。您只需要高质量的 PRNG。 rand() 无处可去,arc4random() 是超调。

有关简单、现代、高质量的随机数生成器,请参阅 this 页面。