一些其他回答中的信息与我的研究结果不一致。我在Windows 8.1上使用Visual Studio 2013进行了测试,一致发现
mersenne_twister_engine
的质量更高且速度显著快于
linear_congruential_engine
或
subtract_with_carry_engine
。这让我相信,在考虑其他回答中的信息时,引擎的具体实现对性能有重大影响。
我相信这并不会让任何人感到惊讶,但其他回答中没有提到
mersenne_twister_engine
速度较慢的情况。我没有其他平台和编译器的测试结果,但在我的配置下,
mersenne_twister_engine
显然是考虑周期、质量和速度性能时更优秀的选择。我没有对内存使用进行分析,因此无法说明空间需求属性。
以下是我用来测试的代码(为了实现可移植性,您只需将
windows.h QueryPerformanceXxx()
API调用替换为适当的计时机制即可):
#include <random>
#include <iostream>
#include <windows.h>
using namespace std;
void test_lc(const int a, const int b, const int s) {
minstd_rand gen(1729);
uniform_int_distribution<> distr(a, b);
for (int i = 0; i < s; ++i) {
distr(gen);
}
}
void test_mt(const int a, const int b, const int s) {
mt19937 gen(1729);
uniform_int_distribution<> distr(a, b);
for (int i = 0; i < s; ++i) {
distr(gen);
}
}
void test_swc(const int a, const int b, const int s) {
ranlux24_base gen(1729);
uniform_int_distribution<> distr(a, b);
for (int i = 0; i < s; ++i) {
distr(gen);
}
}
int main()
{
int a_dist = 0;
int b_dist = 1000;
int samples = 100000000;
cout << "Testing with " << samples << " samples." << endl;
LARGE_INTEGER ElapsedTime;
double ElapsedSeconds = 0;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
double TickInterval = 1.0 / ((double) Frequency.QuadPart);
LARGE_INTEGER StartingTime;
LARGE_INTEGER EndingTime;
QueryPerformanceCounter(&StartingTime);
test_lc(a_dist, b_dist, samples);
QueryPerformanceCounter(&EndingTime);
ElapsedTime.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedSeconds = ElapsedTime.QuadPart * TickInterval;
cout << "linear_congruential_engine time: " << ElapsedSeconds << endl;
QueryPerformanceCounter(&StartingTime);
test_mt(a_dist, b_dist, samples);
QueryPerformanceCounter(&EndingTime);
ElapsedTime.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedSeconds = ElapsedTime.QuadPart * TickInterval;
cout << " mersenne_twister_engine time: " << ElapsedSeconds << endl;
QueryPerformanceCounter(&StartingTime);
test_swc(a_dist, b_dist, samples);
QueryPerformanceCounter(&EndingTime);
ElapsedTime.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedSeconds = ElapsedTime.QuadPart * TickInterval;
cout << "subtract_with_carry_engine time: " << ElapsedSeconds << endl;
}
输出:
使用100000000个样本进行测试。
线性同余发生器时间: 10.0821
梅森旋转演算法发生器时间: 6.11615
带借位发生器时间: 9.26676
std::mt19937
似乎是最常用的通用随机数生成器,但我完全没有事实依据来支持这一点,所以... - Anthonystd::mt19937
,现在每当我需要生成随机数时,我似乎都会使用它,但除了习惯之外,我没有特定的原因。 - Yuushi