Понимание std::atomic::compare_exchange_weak() в C++11C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Понимание std::atomic::compare_exchange_weak() в C++11

Сообщение Anonymous »

Код: Выделить всё

bool compare_exchange_weak (T& expected, T val, ..);

Код: Выделить всё

compare_exchange_weak()
— это один из примитивов сравнения-обмена, представленных в библиотеке std::atomic, представленной в C++11.
Он слабый в том смысле, что может возвращать false, даже если значение объекта равно ожидаемому. Это происходит из-за ложного сбоя на некоторых платформах, где для его реализации используется последовательность инструкций (вместо одной, как на x86). На таких платформах переключение контекста, перезагрузка того же адреса (или строки кэша) другим потоком и т. д. могут привести к сбою примитива. Это ложно, поскольку не сравнение со значением объекта приводит к сбою операции. Вместо этого это своего рода проблемы времени/разногласия.
Но что меня озадачивает, так это то, что сказано в стандарте C++11 (ISO/IEC 14882),

29.6.5
..
Последствием ложного сбоя является то, что почти все случаи использования слабых
сравнений и обменов будут находиться в цикле.

Почему он должен быть в цикле почти во всех случаях ? Означает ли это, что мы будем зацикливаться, если произойдет сбой из-за ложных сбоев? Если это так, то зачем нам использовать Compare_exchange_weak() и писать цикл самостоятельно? Мы можем просто использовать Compare_exchange_strong(), который, я думаю, должен избавить нас от ложных сбоев. Каковы наиболее распространенные случаи использования Compare_exchange_weak()?

Вопрос по теме: В своей книге «Параллелизм C++ в действии» Энтони Уильямс говорит:

Код: Выделить всё

//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:

bool expected=false;
extern atomic b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);

//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.
Почему !expected присутствует в условии цикла? Делается ли это для того, чтобы предотвратить зависание всех потоков и отсутствие прогресса в течение некоторого времени?
Последний вопрос
На платформах, где не существует единой аппаратной инструкции CAS, как слабая, так и сильная версия реализуются с использованием LL/SC (например, PowerPC, ARM до ARMv8.1 и т. д.). Итак, есть ли разница между следующими двумя циклами? Почему, если таковые имеются? (На мой взгляд, они должны иметь схожую производительность.)

Код: Выделить всё

// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }

// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..))
{ .. }
Последний вопрос, который вы, ребята, упомянули, связан с тем, что внутри цикла может быть разница в производительности. Это также упоминается в стандарте C++11 (ISO/IEC 14882):

Когда сравнение и обмен происходит в цикле, слабая версия будет давать
лучшую производительность на некоторых платформах.

Но, как анализировалось выше, две версии в цикле должны давать одинаковую/похожую производительность. Чего мне не хватает?

Подробнее здесь: https://stackoverflow.com/questions/251 ... eak-in-c11
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»