En referencia a (un poco anticuado) paper de Hans Boehm, en "Operaciones atómicas". Menciona que el modelo de memoria (propuesto en ese momento) no evitaría que un compilador de optimización combinara una secuencia de cargas, o almacenes, en la misma variable para que se combinara en una sola carga. Su ejemplo es el siguiente (actualizado a la sintaxis actual es de esperar correcta):Combinación de tiendas/cargas de variables atómicas consecutivas
Dado
atomic<int> v;
El código
while(v.load(memory_order_acquire)) { ... }
podría optimizarse a:
int a = v.load(memory_order_acquire);
while(a) { ... }
Obviamente, esto sería ser malo, como él dice. Ahora mi pregunta es, ya que el documento es un poco viejo, ¿el modelo actual de memoria C++ 0x previene este tipo de optimización, o todavía está técnicamente permitido?
Mi lectura de la norma parece inclinarse hacia su anulación, pero la semántica de uso "adquirir" la hace menos clara. Por ejemplo, si fuera "seq_cst", el modelo parece garantizar que la carga debe participar en un ordenamiento total del acceso y cargar el valor solo una vez parecería violar el orden (ya que rompe la secuencia antes de la relación).
Para adquirir interpreto 29.3.2 para indicar que esta optimización no puede ocurrir, ya que cualquier operación de "liberación" debe ser observada por la operación "adquirir". Hacer solo una adquisición parecería no ser válido.
Entonces mi pregunta es si el modelo actual (en el estándar pendiente) no permitiría este tipo de optimización? Y si es así, ¿qué parte específicamente lo prohíbe? Si no, ¿usar el volatile
atómico resuelve el problema?
Y, como beneficio adicional, si la operación de carga tiene un orden "relajado" ¿se permite entonces la optimización?
Sobre la semántica de la adquisición: Sí, he mal redactado ese bit; la publicación que se muestra establece la relación secuenciada, pero técnicamente no hay garantía de que la haya visto (excepto que tal compilador/CPU podría perder rápidamente todo el mercado). compartir). –
Acerca de 29.3p13, también leí este fragmento y estuve tentado de pensar que es una garantía. Pero debido a que usa el término * tiempo razonable *, no tiene ningún valor y podría simplemente eliminarse del estándar. Es un término sin sentido que significa que no se puede confiar en situaciones de baja latencia. Por ejemplo, en mi proyecto actual, si este tiempo es más de 10s de nanosegundos, no hay ningún valor en absoluto en la operación atómica (digamos en comparación con un bloqueo). –
¿Está de acuerdo, como creo que lo haría, que convertir este atómico en un elemento "volátil" impide que el compilador realice la optimización que ha mostrado? –