Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::mt19937_64 faster than std::mt19937?

Tags:

c++

random

Does mt19937_64 have a higher throughput (bit/s) than the 32 bit version, mt19937, assuming a 64 bit architecture?

What about after vectorization?

like image 760
Chris P Avatar asked Aug 25 '16 20:08

Chris P


1 Answers

As @byjoe points out, this obviously depends on the compiler.

In this case, it seems to be considerably more dependent on the compiler than is typical though. For example, the Boost test linked in the comments uses the compiler from VC++ 2010, and shows only a fairly slight increase in random bits per second from using mt19937_64.

To get more up-to-date information, I whipped up a simple test:

#include <random>
#include <chrono>
#include <iostream>
#include <iomanip>

template <class T, class U>
U test(char const *label, U count) {
    using namespace std::chrono;
    T gen(100);

    U result = 0;

    auto start = high_resolution_clock::now();
    for (U i = 0; i < count; i++)
        result ^= gen();
    auto stop = high_resolution_clock::now();
    std::cout << "Time for " << std::left << std::setw(12) << label
        << duration_cast<milliseconds>(stop - start).count() << "\n";
    return result;
}

int main(int argc, char **argv) {
    unsigned long long limit = 1000000000;

    auto result1 = test<std::mt19937>("mt19937: ", limit);
    auto result2 = test<std::mt19937_64>("mt19937_64: ", limit);

    std::cout << "Ignore: " << result1 << ", " << result2 << "\n";
}

With VC++ 2015 udpate 3 (with /o2b2 /GL, though it probably doesn't matter), I got results like these:

Time for mt19937:    4339
Time for mt19937_64: 4215
Ignore: 2598366015, 13977046647333287932

This shows mt19937_64 as being slightly faster per call, so over twice as fast per bit as mt19937. With MinGW (using -O3), the results were much more like those linked from the Boost site:

Time for mt19937:    2211
Time for mt19937_64: 4183
Ignore: 2598366015, 13977046647333287932

In this case, mt19937_64 takes just a little less than twice the time per call, so it's only slightly faster per bit. The highest overall speed seems to be from g++ with mt19937_64, but the difference between g++ and VC++ (on these runs) is less than 1%, so I'm not sure it's reproducible.

For what it's worth, the difference in speed (per call) between mt19937 and mt19937_64 with VC++ is also pretty small, but does seem to be reproducible--it happened quite consistently in my testing. I did wonder about whether that might be (at least partially) a matter of clock management--that when the code first started, the CPU was idle, and the clock had been slowed, so the first part of the first run was at a lower clock speed. To check, I reversed the order to test mt19937_64 first. I think my hypothesis was at least partially correct--when I reversed the order, mt19937_64 slowed down compared to mt19937, so they were nearly identical on a per-call basis with VC++.

like image 121
Jerry Coffin Avatar answered Sep 28 '22 01:09

Jerry Coffin