c++ multithreading performance c++11 atomic

c++ - ¿Por qué std:: atomic<bool> es mucho más lento que volol bool?



multithreading performance (3)

Código de "Olaf Dietsche"

USE ATOMIC real 0m1.958s user 0m1.957s sys 0m0.000s USE VOLATILE real 0m1.966s user 0m1.953s sys 0m0.010s

SI USTED ESTÁ UTILIZANDO GCC SMALLER 4.7

http://gcc.gnu.org/gcc-4.7/changes.html

Se ha agregado soporte para operaciones atómicas que especifican el modelo de memoria C ++ 11 / C11. Estas nuevas rutinas __atomic reemplazan las rutinas __sync existentes.

Soporte atómico también está disponible para bloques de memoria. Se usarán instrucciones sin bloqueo si un bloque de memoria tiene el mismo tamaño y alineación que un tipo de entero admitido. Las operaciones atómicas que no tienen soporte de bloqueo se dejan como llamadas de función. Un conjunto de funciones de la biblioteca está disponible en la wiki atómica de GCC en la sección "Biblioteca de Atómica Externa".

Así que sí ... la única solución es actualizar a GCC 4.7

He estado usando bool volátil durante años para el control de ejecución de subprocesos y funcionó bien

// in my class declaration volatile bool stop_; ----------------- // In the thread function while (!stop_) { do_things(); }

Ahora, dado que c ++ 11 agregó soporte para operaciones atómicas, decidí probar eso en su lugar

// in my class declaration std::atomic<bool> stop_; ----------------- // In the thread function while (!stop_) { do_things(); }

¡Pero es varios órdenes de magnitud más lento que el volatile bool !

El caso de prueba simple que he escrito toma alrededor de 1 segundo para completar con el enfoque volatile bool . Con std::atomic<bool> sin embargo, he estado esperando unos 10 minutos y ¡me rindí!

Traté de usar memory_order_relaxed flag con load y store con el mismo efecto.

Mi plataforma: Windows 7 64 bit MinGW gcc 4.6.x

¿Qué estoy haciendo mal?

UPD

Sí, sé que volátil no hace que un hilo variable sea seguro. Mi pregunta no es sobre volátil, se trata de por qué atómico es ridículamente lento.

UPD2 @all, gracias por sus comentarios. Intentaré con todo lo sugerido cuando llegue a mi máquina esta noche.


Como tengo curiosidad sobre esto, lo probé en Ubuntu 12.04, AMD 2.3 GHz, gcc 4.6.3.

#if 1 #include <atomic> std::atomic<bool> stop_(false); #else volatile bool stop_ = false; #endif int main(int argc, char **argv) { long n = 1000000000; while (!stop_) { if (--n < 0) stop_ = true; } return 0; }

Compilado con g++ -g -std=c++0x -O3 a.cpp

Aunque, la misma conclusión que @aleguna:

  • solo bool :

    0m0.004s reales
    usuario 0m0,000s
    sys 0m0.004s

  • volatile bool :

    $ tiempo ./a.out
    0m1.413s reales
    usuario 0m1.368s
    sys 0m0.008s

  • std::atomic<bool> :

    $ tiempo ./a.out
    0m32.550s reales
    usuario 0m32.466s
    sys 0m0.008s

  • std::atomic<int> :

    $ tiempo ./a.out
    0m32.091s reales
    usuario 0m31.958s
    sys 0m0.012s


Mi suposición es que esta es una pregunta de hardware. Cuando escribe volátil, le dice al compilador que no asuma nada sobre la variable pero, según tengo entendido, el hardware todavía la tratará como una variable normal. Esto significa que la variable estará en la memoria caché todo el tiempo. Cuando utiliza atómico, utiliza instrucciones de hardware especiales que probablemente signifiquen que la variable se recupera de la memoria principal cada vez que se utiliza. La diferencia en el tiempo es consistente con esta explicación.