Pregunta ¿Por qué std :: atomic es mucho más lento que volol bool?


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 aproximadamente 1 segundo para completar con volatile bool enfoque. Con std::atomic<bool> sin embargo, he estado esperando unos 10 minutos y ¡me rindí!

Intenté usar memory_order_relaxed bandera con load y store para el mismo efecto

Mi plataforma: Windows 7 de 64 bits 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 @todos, gracias por sus comentarios. Intentaré con todo lo sugerido cuando llegue a mi máquina esta noche.


32
2017-10-30 09:15


origen


Respuestas:


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


30
2017-10-30 11:35



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:

  • sólo 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


12
2017-10-30 11:23



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.


2
2017-12-17 14:23