我正在测试 C++ 中随机数生成器的性能,并发现了一些我不明白的非常奇怪的结果。
我已经测试了 std::rand 与使用 std::minstd_rand 的 std::uniform_real_distribution 。
std::rand 计时代码
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000000; ++i)
std::rand();
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Elapsed time: " << elapsed.count() * 1000 << " ms\n";
使用 std:minstd_rand 计时 std::uniform_real_distribution 的代码
std::minstd_rand Mt(std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_real_distribution<float> Distribution(0, 1);
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000000; ++i)
Distribution(Mt);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Elapsed time: " << elapsed.count() * 1000 << " ms\n";
在 Dell Latitude 7390 (I7-8650U 1.9Ghz) 上使用 Microsoft Visual Studio 2019 进行编译时,我获得以下速度:
std::rand -> 经过时间:45.7106 ms
std::uniform_real_distribution -> 经过时间:65.7437 ms
我使用 -D__FMA__ 的附加命令行选项打开了编译器优化
然而,当在 MacOS High Sierra (1.4Ghz i5) 上的 MacBook Air 上使用 g++ 进行编译时,我得到以下速度:
std::rand -> 经过时间:9.4547 ms
std::uniform_real_distribution -> 经过时间:7.9e-05 ms
使用终端命令“g++ prng.cpp -o prng -std=c++17 -O3”
另一个问题是,在Mac上,测试uniform_real_distribution的速度,如果我打印/不打印该值,速度会有所不同。
So
std::minstd_rand Mt(std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_real_distribution<float> Distribution(0, 1);
float num;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000000; ++i)
num = Distribution(Mt);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Elapsed time: " << elapsed.count() * 1000 << " ms\n";
std::cout << num << '\n';
会给我 5.82409 毫秒的时间
而如果不打印,我会得到 7.9e-05 毫秒,请注意,打印只会影响uniform_real_distribution 的测试,我不需要对std::rand 执行此操作。我还使用 mersenne 进行了测试,而不是遇到同样的问题。
我最初认为这是编译器优化在未存储/打印uniform_real_distribution时省略了uniform_real_distribution,因为变量没有被使用,因此可以被省略,但是为什么编译器不为std::rand做同样的事情,为什么这些随机函数在 Mac 上的运行速度比 Windows 上快吗?
编辑:
为了澄清起见,mersenne 指的是使用 std::mt19937_64 而不是 std::minstd_rand 来实现uniform_real_distribution。