variable repetir rango randomize numeros generar funcion decimales arreglo aleatorios c++ random clang mersenne-twister

repetir - generar numeros aleatorios en un arreglo en c++



Caída del rendimiento Clang para la generación de números aleatorios C++ específicos (1)

Utilizando el módulo aleatorio de C ++ 11, encontré una caída de rendimiento impar cuando uso std::mt19937 (versiones de 32 y 64 bits) en combinación con un uniform_real_distribution (float o double, no importa). Comparado con una compilación de g ++, ¡es más que un orden de magnitud más lento!

El culpable no es solo el generador mt, ya que es rápido con uniform_int_distribution . Y no es un defecto general en el uniform_real_distribution ya que es rápido con otros generadores como default_random_engine . Solo esa combinación específica es extrañamente lenta.

No estoy muy familiarizado con las características intrínsecas, pero el algoritmo de Mersenne Twister está más o menos estrictamente definido, por lo que una diferencia en la implementación no podría explicar esta diferencia, supongo. Programa de medida está siguiendo, pero aquí están mis resultados para clang 3.4 y gcc 4.8.1 en una máquina de 64 bits en 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

Programa para generar esto y prueba tú mismo:

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

compilar a través de clang++ -O3 -std=c++11 random.cpp o g ++ respectivamente. ¿Algunas ideas?

editar: Finalmente, Matthieu M. tuvo una gran idea: el culpable es inline, o más bien una falta de eso. Aumentar el límite de alineación clang eliminó la penalización de rendimiento. Eso realmente solucionó una serie de rarezas de rendimiento que encontré. Gracias, aprendí algo nuevo.


Como ya se dijo en los comentarios, el problema es causado por el hecho de que gcc inlines es más agresivo que clang. Si hacemos clang inline muy agresivamente, el efecto desaparece:

Compilando tu código con rendimientos g++ -O3

runtime_int_default: 3000.32 runtime_int_mt: 3112.11 runtime_int_mt_64: 3069.48 runtime_float_default: 859.14 runtime_float_mt: 1027.05 runtime_float_mt_64: 1777.48

mientras clang++ -O3 -mllvm -inline-threshold=10000 yields

runtime_int_default: 3623.89 runtime_int_mt: 751.484 runtime_int_mt_64: 751.132 runtime_float_default: 1072.53 runtime_float_mt: 968.967 runtime_float_mt_64: 1781.34

Aparentemente, ahora clang out-inlines gcc en los casos int_mt , pero todos los otros tiempos de ejecución están ahora en el mismo orden de magnitud. Usé gcc 4.8.3 y clang 3.4 en Fedora 20 64 bit.