我测试了gcc C++标准库的Mersenne twister实现。它比线性同余生成器和C语言的rand()函数表现更优秀,后者很可能是一个LCG(线性同余生成器)。Boost文档似乎也给出了类似的结果,但更青睐于Mersenne twister。有人能解释一下吗?
#include <cstdlib>
#include <iostream>
#include <chrono>
#include <random>
class Timer
{
private:
std::chrono::high_resolution_clock::time_point start_time;
std::chrono::high_resolution_clock::time_point stop_time;
public:
void start()
{
start_time = std::chrono::high_resolution_clock::now();
}
void stop()
{
stop_time = std::chrono::high_resolution_clock::now();
}
double measure()
{
using namespace std::chrono;
return duration_cast<microseconds>
(stop_time - start_time).count() / 1000000.0;
}
};
template<typename T>
class Random
{
private:
T generator;
public:
Random()
: generator
(std::chrono::high_resolution_clock::now().time_since_epoch().count())
{
}
int generate_integer(int begin, int end)
{
return std::uniform_int_distribution<int>(begin, end - 1)(generator);
}
};
int main()
{
constexpr int n = 300000000;
Random<std::minstd_rand> mr;
Random<std::mt19937> mt;
Timer t;
for (int j = 0; j < 3; ++j)
{
t.start();
for (int i = 0; i < n; ++i)
{
static_cast<volatile void>(mr.generate_integer(0, 10));
}
t.stop();
std::cout << "minstd " << t.measure() << std::endl;
t.start();
for (int i = 0; i < n; ++i)
{
static_cast<volatile void>(mt.generate_integer(0, 10));
}
t.stop();
std::cout << "mersenne " << t.measure() << std::endl;
t.start();
for (int i = 0; i < n; ++i)
{
static_cast<volatile void>(std::rand() % 10);
}
t.stop();
std::cout << "rand " << t.measure() << std::endl;
}
}
结果
minstd 4.70876
mersenne 1.55853
rand 4.11873
minstd 4.53199
mersenne 1.55928
rand 4.15159
minstd 4.5374
mersenne 1.55667
rand 4.13715
-O3 -fwhole-program
运行。由于static_cast<volatile void>
,编译器没有优化掉这些语句。 - user3810155static_cast<volatile void>
这个技巧! - Galik