随机数,C ++ 11 vs Boost [英] Random numbers, C++11 vs Boost
问题描述
我想在C ++中生成伪随机数,这两个可能的选项是C ++ 11和Boost对应项的功能.它们的使用方式基本上相同,但是在我的测试中,原生速度大约慢了4倍.
I want to generate pseudo-random numbers in C++, and the two likely options are the feature of C++11 and the Boost counterpart. They are used in essentially the same way, but the native one in my tests is roughly 4 times slower.
是由于库中的设计选择,还是我缺少某种在某处禁用调试代码的方式?
Is that due to design choices in the library, or am I missing some way of disabling debug code somewhere?
更新:代码在此处, https ://github.com/vbeffara/Simulations/blob/master/tests/test_prng.cpp 看起来像这样:
Update: Code is here, https://github.com/vbeffara/Simulations/blob/master/tests/test_prng.cpp and looks like this:
cerr << "boost::bernoulli_distribution ... \ttime = ";
s=0; t=time();
boost::bernoulli_distribution<> dist(.5);
boost::mt19937 boostengine;
for (int i=0; i<n; ++i) s += dist(boostengine);
cerr << time()-t << ", \tsum = " << s << endl;
cerr << "C++11 style ... \ttime = ";
s=0; t=time();
std::bernoulli_distribution dist2(.5);
std::mt19937_64 engine;
for (int i=0; i<n; ++i) s += dist2(engine);
cerr << time()-t << ", \tsum = " << s << endl;
(使用std::mt19937
而不是std::mt19937_64
会使它在我的系统上更慢.)
(Using std::mt19937
instead of std::mt19937_64
makes it even slower on my system.)
推荐答案
那很漂亮可怕的.
让我们看看:
boost :: bernoulli_distribution<>
boost::bernoulli_distribution<>
if(_p == RealType(0))
return false;
else
return RealType(eng()-(eng.min)()) <= _p * RealType((eng.max)()-(eng.min)());
std :: bernoulli_distribution
std::bernoulli_distribution
__detail::_Adaptor<_UniformRandomNumberGenerator, double> __aurng(__urng);
if ((__aurng() - __aurng.min()) < __p.p() * (__aurng.max() - __aurng.min()))
return true;
return false;
两个版本都调用引擎,并检查输出是否在与给定概率成比例的值范围内.
Both versions invoke the engine and check if the output lies in a portion of the range of values proportional to the given probability.
最大的区别在于,gcc版本调用了助手类_Adaptor
的函数.
The big difference is, that the gcc version calls the functions of a helper class _Adaptor
.
此类的min
和max
函数分别返回0
和1
,然后operator()
然后使用给定的URNG调用std::generate_canonical
以获取介于0
和1
之间的值.
This class’ min
and max
functions return 0
and 1
respectively and operator()
then calls std::generate_canonical
with the given URNG to obtain a value between 0
and 1
.
std::generate_canonical
是带有循环的20行函数–在这种情况下,它永远不会重复多次,但会增加复杂性.
std::generate_canonical
is a 20 line function with a loop – which will never iteratate more than once in this case, but it adds complexity.
除此之外,boost仅在发行版的构造函数中使用param_type
,然后将_p
保存为double
成员,而gcc具有param_type
成员,并且必须获取"值它的.
Apart from that, boost uses the param_type
only in the constructor of the distribution, but then saves _p
as a double
member, whereas gcc has a param_type
member and has to "get" the value of it.
这一切融合在一起,编译器无法进行优化. 铛声在它上面窒息了更多.
This all comes together and the compiler fails in optimizing. Clang chokes even more on it.
如果您锤子足够硬,您甚至可以获得std::mt19937
和boost::mt19937
en等于gcc.
If you hammer hard enough you can even get std::mt19937
and boost::mt19937
en par for gcc.
也可以测试libc ++,也许以后再补充.
It would be nice to test libc++ too, maybe i’ll add that later.
经过测试的版本:boost 1.55.0,gcc 4.8.2的libstdc ++标头
根据要求提供行号^^
tested versions: boost 1.55.0, libstdc++ headers of gcc 4.8.2
line numbers on request^^
这篇关于随机数,C ++ 11 vs Boost的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!