2011-02-09 11 views
19

Aún no estoy seguro si soy yo el que no entiende o si la documentación no está claramente formulada. El siguiente extracto ha sido tomado de la más reciente proyecto (N3126, sección 29.6):std :: atomic | compare_exchange_weak vs. compare_exchange_strong

bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired); 
bool atomic_compare_exchange_weak(A* object, C * expected, C desired); 
bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired); 
bool atomic_compare_exchange_strong(A* object, C * expected, C desired); 
bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile; 
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile; 
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure); 
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; 
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst); 
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; 
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst); 

Observación: La debilidad de comparación y el intercambio operaciones pueden fallar falsamente, que es decir, volver falsa, dejando el contenido de la memoria señalada por esperado antes de la operación es el mismo que el del objeto y el mismo que el esperado después de la operación. [Nota: esta falsa falla de permite la implementación de compare-and-exchange en una clase más amplia de máquinas , por ejemplo, máquinas de almacenamiento condicional de cargadas a máquina. Una consecuencia de falla espuria es que casi todos los usos de débil comparar y cambiar estarán en un bucle .

Entonces, ¿qué significa esto? En primer lugar, 'puede' faild falsamente ?! Por qué lo hace? ¿Y cómo definen 'pueden'? En segundo lugar, no sé por qué, pero todavía no tengo idea de cuál es la diferencia entre las funciones con el sufijo "_strong" y "_weak".

Espero que alguien pueda ayudar;) Saludos cordiales.

EDIT: Eso es lo que he encontrado en libstdC++ - aplicación (atomic_0.h):

bool compare_exchange_weak(
    __integral_type& __i1, 
    __integral_type __i2, 
    memory_order __m1, 
    memory_order __m2 
) 
{ 
    __glibcxx_assert(__m2 != memory_order_release); 
    __glibcxx_assert(__m2 != memory_order_acq_rel); 
    __glibcxx_assert(__m2 <= __m1); 
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); 
} 

bool compare_exchange_strong(
    __integral_type& __i1, 
    __integral_type __i2, 
    memory_order __m1, 
    memory_order __m2 
) 
{ 
    __glibcxx_assert(__m2 != memory_order_release); 
    __glibcxx_assert(__m2 != memory_order_acq_rel); 
    __glibcxx_assert(__m2 <= __m1); 
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); 
} 
+0

Agregué la etiqueta STL, con la esperanza de que traerá a Howard Hinnant allí, ha estado trabajando en la implementación de estos en libC++, por lo que debería saberlo. –

Respuesta

7

Tiene que ver con el modelo de consistencia de memoria compartida que implementa el hardware. Para aquellas arquitecturas de hardware que implementan algún tipo de modelo de consistencia relajada (por ejemplo, semántica de lanzamiento), las operaciones fuertes a las que se refiere arriba pueden tener una sobrecarga alta, y así los expertos pueden usar las formas más débiles para implementar algoritmos que funcionan bien también en esa consistencia relajada arquitecturas.

Para obtener más información, consulte p. Ej.

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

Capítulo 12 y el Apéndice C en http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html

+1

Pero, ¿no es el sentido del parámetro memory_order para fortalecer o debilitar el modelo de ordenamiento de memoria? – 0xbadf00d

+0

No, eso lo especifica el hardware. Ese parámetro especifica el orden mínimo que su algoritmo requiere para funcionar correctamente. A continuación, se inicia la implementación de C++ 0x para asegurarse de que al menos el orden especificado es proporcionado, para archit fuertemente ordenado como x86, es probable que tanto las implementaciones fuertes como las débiles sean las mismas. – janneb

+0

Sry, pero todavía no tiene sentido para mí. ¿No es redundante especificar el orden a través del parámetro memory_order y los métodos fuertes o débiles? Tal vez sería útil saber cuál es la diferencia principal (abstracta) entre el intercambio de comparación débil y fuerte. – 0xbadf00d

25

La nota da una pista, en referencia a LL/SC arquitecturas. Del artículo de Wikipedia:

Si se ha producido alguna actualización, se garantiza que la tienda-condicional falla, incluso si el valor leído por el enlace de carga se ha restaurado desde entonces. Como tal, un par LL/SC es más fuerte que una lectura seguida de un compare-and-swap (CAS), que no detectará actualizaciones si el valor anterior ha sido restaurado (ver problema ABA).

Las implementaciones reales de LL/SC no siempre tienen éxito si no hay actualizaciones concurrentes en la ubicación de la memoria en cuestión. Cualquier evento excepcional entre las dos operaciones, como un cambio de contexto, otro enlace de carga o incluso (en muchas plataformas) otra carga o operación de tienda, provocará que el condicional de tienda falle falsamente.

en chips/SC LL del compare_exchange se pondrán en práctica en términos de LL/SC, que falsamente pueden fallar, por lo compare_exchange_strong necesidades sobrecarga adicional para volver a intentar en el caso de fallo. Al proporcionar compare_exchange_strong y compare_exchange_weak, el programador puede decidir si desea que la biblioteca maneje fallas espúreas (en cuyo caso usaría compare_exchange_strong o si desea manejarlo en su propio código (en cuyo caso usaría compare_exchange_weak))

+0

Buena respuesta. Una cosa para discutir es sobre "volver a intentar en caso de falla", ¿debería ser "volver a intentar en el caso de una falsa *** falsa"? Si eso es un verdadero error debido a la contención (el valor de destino no es igual al esperado), 'compare_exchange_strong' debe devolver' false' inmediatamente sin ningún reintento. ¿Estás de acuerdo? –

+0

Publiqué una pregunta con respecto a 'compare_exchange_weak' [aquí] (http://stackoverflow.com/questions/25199838/understanding-of-stdatomiccompare-exchange-weak-in-c11). ¿Te importaría echar un vistazo y compartir algunos conocimientos que conoces con nosotros? Gracias. –

+0

Sí, la forma fuerte vuelve a intentar en caso de falla espuria, no cuando el objeto no tiene el valor esperado. –

Cuestiones relacionadas