std::mt19937_64比std::mt19937更快吗?

6

假设使用64位架构,mt19937_64的吞吐量(比特/秒)是否比32位版本mt19937更高?

进行矢量化后呢?


这里是随机数生成器(PRNG)的性能比较,它们是与boost一起提供的实现 - http://www.boost.org/doc/libs/release/doc/html/boost_random/performance.html - Praetorian
你有试过吗,或者其他什么吗? - Mikhail
根据Boost基准测试,以每秒比特数为单位,mt19937_64似乎比mt19937慢两倍。然而,基本基准测试表明,mt19937_64实际上是mt19937的两倍速度。 - Chris P
2个回答

7

正如@byjoe指出的那样,这显然取决于编译器。

在这种情况下,它似乎比通常更依赖于编译器。例如,在评论中链接的Boost测试使用了VC++ 2010的编译器,仅显示了从使用mt19937_64获得的随机位数每秒略微增加。

为了获得更多最新信息,我进行了一个简单的测试:

#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";
}

使用VC++ 2015更新3(带有/o2b2 /GL,尽管这可能并不重要),我得到了以下结果:

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

这表明mt19937_64每次调用比mt19937稍微快一些,因此每位速度是mt19937的两倍以上。使用MinGW(使用-O3)时,结果更像与从Boost网站链接的结果:

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

在这种情况下,mt19937_64 每次调用所需的时间仅比两倍略小,因此每位元速度只略快。总体上最高的速度似乎来自于使用 mt19937_64 的 g++,但是 g++ 和 VC++(在这些运行中)之间的差异不到 1%,因此我不确定它是否可重复。
值得注意的是,使用 VC++,mt19937 和 mt19937_64 每次调用之间的速度差异(每次调用)也很小,但确实可以重现-在我的测试中相当一致地发生。我想知道这是否可能(至少部分)是时钟管理的问题-当代码首次启动时,CPU 处于空闲状态,并且时钟已经减慢,因此第一次运行的前面一部分以较低的时钟速度运行。为了检查,我反转了顺序以先测试 mt19937_64。我认为我的假设至少部分正确-当我反转顺序时,与 mt19937 相比,mt19937_64 会减速,因此它们在使用 VC++ 进行每次调用时几乎相同。

1
我使用GCC 4.8.2(x86_64)在Windows子系统上的Linux上进行基准测试,使用-O2,并获得了60次试验的数据,每次计算1e9个随机数在i7-3820上。平均完成时间为3.576秒,其中mt19937略快(<1%)。这使mt19937_64快两倍。我怀疑Boost结果是使用32位编译器得出的。据我所知,大多数MinGW构建都是x86。 - Chris P

6

这显然取决于您的编译器及其实现。我刚刚进行了测试,64位版本每次调用所需的时间大约比32位版本长60%,因此64位版本的每个比特位速度大约快25%。我使用了i7 CPU 进行了测试。

如果您需要最大速度,则可能需要考虑使用其他工具。特别是如果数字不需要非常高的质量。


事实上,Mersenne Twister似乎非常快,比如请见http://www.boost.org/doc/libs/1_61_0/doc/html/boost_random/reference.html#boost_random.reference.generators或者http://www.cacert.at/cgi-bin/rngresults,至少相对于你要用随机数的目的而言,它是很快的。 - Baum mit Augen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接