2012-01-12 3 views
27

Soy un novato cuando se trata de esto. ¿Podría alguien proporcionar una explicación simplificada de las diferencias entre las siguientes barreras de memoria?C++ para Atomics

  • Las ventanas MemoryBarrier();
  • La valla _mm_mfence();
  • El ensamblador en línea asm volatile ("" : : : "memory");
  • El intrínseca _ReadWriteBarrier();

Si no hay una explicación sencilla algunos buenos enlaces a artículos o libros se probablemente me ayude a entenderlo. Hasta ahora, estaba bien con el uso de objetos escritos por otros envolviendo estas llamadas, pero me gustaría tener una mejor comprensión que mi pensamiento actual, que básicamente se basa en que hay más de una forma de implementar barreras de memoria debajo de las cubiertas.

+4

se olvidó de C++ 11s 'atomic_thread_fence' – Grizzly

+0

Bueno, eso es lo que esto conduce a ... tenemos nuestro propio objeto plantilla atómica para tipos integrales y estoy queriendo cambiar a C++ 11 estándar atómico. Antes de hacerlo, quiero entender la implementación subyacente de cómo funcionan ambas cosas. – AJG85

Respuesta

28

Tanto MemoryBarrier (MSVC) como _mm_mfence (admitidos por varios compiladores) proporcionan una valla de memoria de hardware, que evita que el procesador mueva lecturas y escrituras a través de la guía.

La principal diferencia es que MemoryBarrier tiene implementaciones específicas de plataforma para x86, x64 e IA64, donde como _mm_mfence utiliza específicamente la instrucción SSE2 mfence, por lo que no siempre está disponible.

En x86 y x64 MemoryBarrier se implementa con un xchg y lock or respectivamente, y he visto algunas afirmaciones de que esto es más rápido que mfence. Sin embargo, mis propios puntos de referencia muestran lo contrario, por lo que aparentemente depende mucho del modelo de procesador.

Otra diferencia es que mfence también se puede usar para ordenar tiendas/cargas no temporales (movntq, etc.).

GCC también tiene __sync_synchronize que genera una cerca de hardware.

asm volatile ("" : : : "memory") en GCC y _ReadWriteBarrier en MSVC solo proporcionan una valla de memoria de nivel de compilación, evitando que el compilador reordena los accesos a la memoria. Eso significa que el procesador todavía está en libertad de hacer un nuevo pedido.

vallas compilador se utilizan generalmente en combinación con las operaciones que tienen algún tipo de valla de hardware implícita. P.ej. en x86/x64 todas las tiendas tienen una valla de liberación y las cargas tienen una valla de adquisición, por lo que solo necesita una valla de compilación cuando implemente load-acquire y store-release.

+0

¡perfecto! gracias, eso ayudó mucho. – AJG85

3

Véase mi respuesta here en la semántica de nivel de hardware de cercas. Lo que no se menciona allí es que también impiden reordenamiento de cargas, almacenes o tiendas de cargas & (dependiendo de la valla) a través de vallas, tanto a nivel compilador y el nivel de hardware.