2010-05-26 16 views
5

Los actuales estados C++0x draft en la sección 29.3.9 y 29.3.10, páginas 1111-1112 que en el siguiente ejemplo:C++ 0x: Memoria ordenar

// Thread 1 
r1 = y.load(memory_order_relaxed); 
x.store(1, memory_order_relaxed); 

// Thread 2 
r2 = x.load(memory_order_relaxed); 
y.store(1, memory_order_relaxed); 

El resultado r1 = r2 = 1 es posible ya que las operaciones de cada hilo está relajado y en direcciones no relacionadas. Ahora mi pregunta es acerca de los posibles resultados de la siguiente ejemplo (similar):

// Thread 1 
r1 = y.load(memory_order_acquire); 
x.store(1, memory_order_release); 

// Thread 2 
r2 = x.load(memory_order_acquire); 
y.store(1, memory_order_release); 

Creo que en este caso el resultado r1 = r2 = 1 no es posible. Si fuera posible, la carga de y se sincronizaría con (por lo tanto, antes) la tienda en y. De forma similar a x, la carga de x ocurriría antes de la tienda a x. Pero la carga de y se secuencia antes (por lo tanto, también ocurre antes) la tienda en x. Esto crea una relación cíclica de pasar antes que creo que no está permitida.

+0

Cambié el título, ya que el problema per se no tiene nada que ver con las tiendas especulativas. Para tiendas especulativas, consulte http://stackoverflow.com/questions/2001913/c0x-memory-model-and-speculative-loads-stores – janneb

+0

La especulación de tienda es la palabra clave aquí porque el resultado 'r1 = r2 = 1' requiere las tiendas ser reordenado ("especulado") antes de ambas lecturas. Tu título es demasiado vago. –

+0

Tienda especulativa en el contexto de los documentos de trabajo C++ 0x se refiere a la especulación del compilador, vea la pregunta a la que me he vinculado en mi comentario anterior. Su pregunta tiene que ver con reordenar que el hardware sí lo hace (dependiendo del modelo de coherencia de memoria compartida implementado por la arquitectura de hardware) y cómo C++ 0x proporciona las funciones para restringir este reordenamiento de memoria emitiendo varias instrucciones de barrera de memoria. Por lo tanto, creo que el título que proporcioné es más apropiado que el título original; pero bueno, es tu pregunta, así que siéntete libre de cambiarla a lo que desees. – janneb

Respuesta

4

Si tomamos el tiempo (o, secuencias de instrucciones si se quiere) a fluir hacia abajo, al igual que la lectura de código, entonces mi entendimiento es que

  • Una adquirir valla permite que otros accesos a memoria a moverse hacia abajo más allá de la valla , pero no hacia arriba más allá de la valla
  • Una valla de liberación permite que otros accesos a memoria a moverse hacia arriba más allá de la valla, pero no hacia abajo más allá de la valla

En otras palabras, si usted tiene un código como

acquire 
// other stuff 
release 

luego los accesos a la memoria pueden moverse desde fuera del par adquirir/liberar al interior, pero no al revés (y tampoco pueden omitir el par adquirir/liberar).

Con la semántica de consistencia relajada en su primer ejemplo en la pregunta, el hardware puede reordenar accesos de memoria de modo que los almacenes ingresen al sistema de memoria antes de las cargas, permitiendo r1 = r2 = 1. Con la semántica de adquisición/liberación en el segundo ejemplo, se evita ese reordenamiento y, por lo tanto, r1 = r2 = 1 no es posible.

+0

No estoy seguro de entender su respuesta. –

+0

Hmm, ¿me ayuda mi aclaración? Si no, ¿qué es lo que específicamente no entiendes? – janneb

+0

Tome mi segundo ejemplo, reemplace las versiones de relaxeds, adquiere estancias adquiere. ¿Es posible r1 = r2 = 1? Ahora reinicie desde la versión inicial del segundo ejemplo otra vez, pero esta vez reemplace adquiere por relajado y mantenga las versiones como están. ¿Es posible r1 = r2 = 1? –