mercredi 6 novembre 2019

Random number generator performance varies between platforms

I am testing the performance of random number generators in c++ and have come upon some very strange results that I do not understand.

I have tested std::rand vs std::uniform_real_distribution which uses std::minstd_rand.

Code for timing 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";

Code for timing std::uniform_real_distribution with 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";

When compiling with Microsoft Visual Studio 2019, on a Dell Latitude 7390 (I7-8650U 1.9Ghz) I get the following speeds:

std::rand -> Elapsed time: 45.7106 ms std::uniform_real_distribution -> Elapsed time: 65.7437 ms

I have compiler optimizations turned on with the additional command line option of -D__FMA__

However when compiling with g++ on a MacBook Air on MacOS High Sierra (1.4Ghz i5) I get the following speeds:

std::rand -> Elapsed time: 9.4547 ms std::uniform_real_distribution -> Elapsed time: 7.9e-05 ms

using terminal command "g++ prng.cpp -o prng -std=c++17 -O3"

Another problem was that on Mac, testing the speed of uniform_real_distribution the speed would vary if I did / did not print the value.

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';

would give me time of 5.82409 ms

whereas without printing I get 7.9e-05 ms, Note that printing only effects the test for uniform_real_distribution, I do not need to do this for std::rand. I also tested using mersenne instead of which does not suffer from the same issue.

I originally thought that this was compiler optimizations omitting the uniform_real_distribution when it wasn't stored / printed as the variable isn't used and thus can be omitted but then why doesn't the compiler do the same for std::rand, and why do these random functions run faster on Mac than Windows?

EDIT: For clarification mersenne is referring to std::mt19937_64 being used instead of std::minstd_rand for uniform_real_distribution.




Aucun commentaire:

Enregistrer un commentaire