2011-02-09 5 views
19

Я все еще не уверен, что это я не понимаю, или документация четко не сформулирована. Следующий отрывок был взят из нового проекта (N3126, раздел 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); 

Замечание: Слабое сравнения и обмена операции может произойти сбой поддельно, что есть, вернуться ложным, оставляя содержание памяти, на которое указывает , ожидаемое до операции , такое же, как и у объекта , и то же, что и ожидаемое после операции. [Примечание: этот ложный отказ позволяет реализовать сравнение и обмену по более широкому классу машин , например, с загрузкой машин-условных машин. A Последствием ложного отказа является , что почти все виды использования слабых сравниваются и обмениваются в цикле .

Итак, что это значит? Во-первых, это может «не так» ложно ?! Почему это происходит? И как они определяют «может»? Во-вторых, я не знаю почему, но я до сих пор не знаю, в чем разница между функциями с суффиксами «_strong» и «_weak».

Надеюсь, что кто-нибудь может помочь;) С уважением.

EDIT: Вот что я нашел в libstdC++ - реализация (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

Я добавил тэг STL, надеясь, что он принесет Ховарда Хиннанта там, он работает над их внедрением в libC++, поэтому он должен знать об этом. –

ответ

7

Это связано с общей памятью непротиворечивости модели, что аппаратное обеспечение реализует. Для тех аппаратных архитектур, которые реализуют какую-то непринужденную модель согласованности (например, семантику выпуска), сильные операции, о которых вы говорите выше, могут иметь высокие накладные расходы, и поэтому эксперты могут использовать более слабые формы для реализации алгоритмов, которые хорошо работают и на такой непринужденной консистенции архитектуры.

Для получения дополнительной информации см., Например,

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

Глава 12 и Приложение C в http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html

+1

Но, разве смысл параметра memory_order не усиливает и не ослабляет модель заказа памяти – 0xbadf00d

+0

Нет, это указано аппаратным обеспечением. Этот параметр указывает минимальный порядок, который требует ваш алгоритм для правильной работы. Затем выполняется реализация C++ 0x, чтобы убедиться, что, по крайней мере, указанное упорядочение при условии, что для строго упорядоченного архита таких как x86, вполне вероятно, что и сильные, и слабые реализации одинаковы. – janneb

+0

Sry, но это все еще не имеет смысла для меня. Разве не является избыточным указывать порядок с помощью параметра memory_order и сильных или слабых методов? Возможно, это поможет узнать, что является главной (абстрактной) разницей между слабым и сильным сравнением. – 0xbadf00d

25

Нота дает подсказку, ссылаясь на LL/SC архитектур. Из статьи в Википедии:

Если какие-либо обновления произошли, гарантируется сбой в состоянии хранилища, даже если значение, считанное ссылкой на загрузку, было восстановлено. Таким образом, пара LL/SC сильнее, чем чтение, за которым следует сравнение и своп (CAS), которая не будет обнаруживать обновления, если старое значение было восстановлено (см. Проблему ABA).

Реальные реализации LL/SC не всегда успешны, если нет параллельных обновлений в рассматриваемой ячейке памяти. Любые исключительные события между двумя операциями, такие как контекстный переключатель, другая ссылка загрузки или даже (на многих платформах) другая операция загрузки или хранения, приведут к тому, что условие хранилища будет ложно терпеть неудачу.

На LL/SC чипсов compare_exchange будут реализованы в терминах LL/SC, которые могут поддельно терпят неудачу, поэтому compare_exchange_strong нуждается в дополнительных накладных, чтобы повторить попытку в случае неудачи. Предоставление как compare_exchange_strong, так и compare_exchange_weak позволяет программисту решить, хотят ли они, чтобы библиотека обрабатывала ложные сбои (в этом случае они будут использовать compare_exchange_strong или если они хотят обрабатывать ее в своем собственном коде (в этом случае они будут использовать compare_exchange_weak)

+0

Хороший ответ. Одна вещь, которую нужно обсудить, это «повторить попытку в случае неудачи», следует ли «повторить попытку в случае *** ложного *** отказа»? Если это истинный сбой из-за конкуренции (значение dest не равно ожидаемому), 'compare_exchange_strong' должен возвращать' false' сразу после любой попытки. Вы согласны? –

+0

Я задал вопрос относительно 'compare_exchange_weak' [здесь] (http://stackoverflow.com/questions/25199838/understanding-of-stdatomiccompare-exchange-weak-in-c11). Не могли бы вы взглянуть и поделиться знаниями, которые вы знаете с нами? Благодарю. –

+0

Да, сильная форма повторяет в случае ложного отказа, а не когда объект не имеет ожидаемого значения. –

Смежные вопросы