Я тестирую производительность генераторов случайных чисел в c ++ и натолкнулся на некоторые очень странные результаты, которые я не понимаю.
Я протестировал std :: rand vs std ::iform_real_distribution, который использует std:: minstd_rand.
Код для синхронизации 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 ::iform_real_distribution с использованием std: minstd_rand
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";
При компиляции с Microsoft VisualStudio 2019, на Dell Latitude 7390 (I7-8650U 1,9 ГГц) я получаю следующие скорости:
std :: rand -> Истекшее время: 45,7106 мс std ::iform_real_distribution -> Истекшее время: 65,7437 мс
У меня включена оптимизация компилятора с дополнительной опцией командной строки -D__FMA __
Однако при компиляции с g ++ на MacBook Air на MacOS High Sierra (1.4Ghz i5) я получаю следующие скорости:
std :: rand -> Истекшее время: 9,4547 мс std ::iform_real_distribution -> Истекшее время: 7,9e-05 мс
с помощью команды терминала "g ++ prng.cpp -oprng -std = c ++ 17 -O3 "
Еще одна проблема заключалась в том, что на Mac, при тестировании скоростиiform_real_distribution, скорость менялась бы, если бы я делал / не печатал значение.
Так
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 мс. Обратите внимание, что печать влияет только на тест дляiform_real_distribution, мне не нужно это делатьдля std :: rand. Я также протестировал использование mersenne вместо которого не страдает от той же проблемы.
Изначально я думал, что это были оптимизации компилятора, в которых пропущен файлiform_real_distribution, когда он не был сохранен / напечатан, поскольку переменная не используется и, таким образом,может быть опущено, но тогда почему компилятор не делает то же самое для std :: rand, и почему эти случайные функции выполняются на Mac быстрее, чем Windows?
EDIT: для пояснения, mersenne ссылается на std ::mt19937_64 используется вместо std :: minstd_rand дляiform_real_distribution.