【发布时间】:2015-11-08 18:13:07
【问题描述】:
我使用 gcc C++ 标准库的 Mersenne twister 实现进行了测试。它优于线性同余生成器和 Crand,这很可能是 LCG。 A boost documentation 似乎也给出了类似的结果,但更偏爱梅森捻线机。谁能解释一下?
#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
【问题讨论】:
-
您期待不同的结果吗?
-
@zenith 当然,LCG 只是一些算术运算,而 mt19937 是几页代码。
-
你开启优化了吗?为了获得良好的结果,您应该打开完全优化并强制定时活动产生副作用(累积校验和?),例如在计时器停止之后打印校验和结果,以防止编译器优化定时活动离开。
-
@Galik 测试使用
-O3 -fwhole-program运行。由于static_cast<volatile void>,编译器没有优化掉语句。 -
@xiver77 啊好想知道
static_cast<volatile void>这个把戏!