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.004svolatile bool
:$ tiempo ./a.out
0m1.413s reales
usuario 0m1.368s
sys 0m0.008sstd::atomic<bool>
:$ tiempo ./a.out
0m32.550s reales
usuario 0m32.466s
sys 0m0.008sstd::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.