使用C++ 11的随机模块时,当使用std::mt19937
(32位和64位版本)和uniform_real_distribution
(float或double,无所谓)组合时, 。与g ++编译相比,它的速度要慢一个数量级!特定C++随机数生成的Clang性能下降
罪魁祸首不仅仅是mt发电机,因为它的速度很快,uniform_int_distribution
。它不是uniform_real_distribution
中的一个普通缺陷,因为其他生成器如default_random_engine
的速度很快。只是这种特定的组合很古怪。
我对intrinsics不是很熟悉,但是Mersenne Twister算法或多或少有严格的定义,所以实现上的差异不能解释我猜想的这种差异吗?测量计划是继,但这里是我对铛3.4和gcc 4.8.1在64位Linux机器上的结果:
gcc 4.8.1
runtime_int_default: 185.6
runtime_int_mt: 179.198
runtime_int_mt_64: 175.195
runtime_float_default: 45.375
runtime_float_mt: 58.144
runtime_float_mt_64: 94.188
clang 3.4
runtime_int_default: 215.096
runtime_int_mt: 201.064
runtime_int_mt_64: 199.836
runtime_float_default: 55.143
runtime_float_mt: 744.072 <--- this and
runtime_float_mt_64: 783.293 <- this is slow
计划产生这一点,并尝试自己:
#include <iostream>
#include <vector>
#include <chrono>
#include <random>
template< typename T_rng, typename T_dist>
double time_rngs(T_rng& rng, T_dist& dist, int n){
std::vector< typename T_dist::result_type > vec(n, 0);
auto t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; ++i)
vec[i] = dist(rng);
auto t2 = std::chrono::high_resolution_clock::now();
auto runtime = std::chrono::duration_cast<std::chrono::microseconds>(t2-t1).count()/1000.0;
auto sum = vec[0]; //access to avoid compiler skipping
return runtime;
}
int main(){
const int n = 10000000;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine rng_default(seed);
std::mt19937 rng_mt (seed);
std::mt19937_64 rng_mt_64 (seed);
std::uniform_int_distribution<int> dist_int(0,1000);
std::uniform_real_distribution<float> dist_float(0.0, 1.0);
// print max values
std::cout << "rng_default_random.max(): " << rng_default.max() << std::endl;
std::cout << "rng_mt.max(): " << rng_mt.max() << std::endl;
std::cout << "rng_mt_64.max(): " << rng_mt_64.max() << std::endl << std::endl;
std::cout << "runtime_int_default: " << time_rngs(rng_default, dist_int, n) << std::endl;
std::cout << "runtime_int_mt: " << time_rngs(rng_mt_64, dist_int, n) << std::endl;
std::cout << "runtime_int_mt_64: " << time_rngs(rng_mt_64, dist_int, n) << std::endl;
std::cout << "runtime_float_default: " << time_rngs(rng_default, dist_float, n) << std::endl;
std::cout << "runtime_float_mt: " << time_rngs(rng_mt, dist_float, n) << std::endl;
std::cout << "runtime_float_mt_64: " << time_rngs(rng_mt_64, dist_float, n) << std::endl;
}
通过clang++ -O3 -std=c++11 random.cpp
编译或g ++。有任何想法吗?
编辑:最后,Matthieu M.有一个好主意:罪魁祸首是内联,或者说是缺乏。增加内联限制消除了性能损失。这实际上解决了我遇到的一些性能怪异问题。谢谢,我学到了一些新东西。
也许你想分析一些东西(例如用callgrind)并比较生成的汇编器... – PlasmaHH
我只能为'float_mt'情况而不是'float_mt_64'重现此事。我在Fedora 20 64位上使用clang3.4的代码。 –
打算发布一个错误报告,但我看到你已经做到了,http://llvm.org/bugs/show_bug.cgi?id=19542 – pyCthon