Могут ли нагрузки проскальзывать под операцией получения / могут ли магазины перемещаться выше выпуска в C++?
TL / DR: правда ли, что только 1 (а не 2) из 4 переупорядочений разрешено для операций приобретения / выпуска? Если так, то почему?
На данный момент из того, что я понял о семантике acqu-release, является то, что (в основном)
- операция получения не позволяет грузам / хранилищам под ней плавать над ней
- операция освобождения не позволяет грузам / хранилищам выше этого скользить ниже этого
Но меньше говорится об обратном направлении.
Из некоторых источников (блоги Джеффа Прешинга и других, а некоторые руководства по архитектуре, по-видимому, подразумевают это), я читал, что операции получения / выпуска эквивалентны (атомный операционный блок + барьер памяти в данном месте памяти)/(барьер памяти + атомный оператор)) соответственно.
Они описывают 4 вида барьеров памяти и говорят, что, например, операция получения использует барьер, который похож на LoadLoad + LoadStore (и похож на выпуск).
Как я понимаю, эти барьеры (соответственно LoadLoad + LoadStore и StoreStore + LoadStore) позволяют:
магазин проскользнуть под приобретение
нагрузка, чтобы плавать выше выпуска
И груз не может проскользнуть под приобретением / магазин не может плавать выше выпуска.
Это вообще правильно? Это правильно для C++? Отличается ли C++ от общего значения?
(Потому что, например, в этом ответе говорится, что нагрузка может проскользнуть под приобретением (насколько я понимаю). У меня также было несколько источников, в которых говорилось, что что-либо может проскользнуть под приобретением (и наоборот).)
Если это правильно, в чем причина этого? Я пытался придумать что-то вроде (для выпуска):
x.store(5, std::memory_order_release);
y.store(true, std::memory_order_relaxed);
И другой поток, читающий их в другом порядке, был бы плохим, учитывая, что он используется в шаблонах, таких как двойная проверка блокировки.
Это близко к причине? Если да, может ли кто-нибудь привести убедительные примеры как приобретения, так и выпуска?
В то время как для магазина, скользящего под сборкой / загрузкой, плавающей над релизом, (вероятно) таких недостатков нет...
1 ответ
Барьеры памяти могут использоваться для реализации семантики загрузки-накопления и освобождения хранилища, но они предоставляют более строгие, чем требуется, гарантии, как указано в статье Джеффа Прешинга:
Обратите внимание, что эти барьеры технически более строгие, чем то, что требуется для получения и выпуска семантики в одной операции памяти, но они достигают желаемого эффекта.
Если вы поместите барьер (ы) LoadLoad + LoadStore между загрузкой и последующими операциями с памятью, то все нагрузки до барьера в программном порядке не могут быть переупорядочены после барьера, и все последующие обращения к памяти не могут быть переупорядочены до барьера. Это более строго, чем необходимо для реализации семантики получения для конкретной операции загрузки, потому что барьер упорядочивает все предыдущие нагрузки, а не только конкретную нагрузку, которая должна иметь семантику получения. Так что они не совсем эквивалентны. То же самое касается семантики релиза магазина. Херб Заикание написал комментарий относительно этого:
Да, это ошибка в моей презентации (слов больше, чем фактический слайд). Пример в порядке, но я должен исправить описание "если это был забор релиза". Особенно:
начиная с 1:10:30, я ошибся, говоря, что у забора релиза есть проблема с корректностью, потому что это позволяет магазинам всплывать (это не так, как отмечалось, как правило, в 29.8.2; спасибо!) - что я должен Я сказал, что это все еще пессимизация производительности, потому что ограждение не связано с предназначенным для этого хранилищем, но поскольку мы не знаем, какое следующее хранилище должно пессимистически применяться ко ВСЕМ последующим обычным хранилищам до следующей применяемой специальной точки синхронизации операций с памятью - это толкает их всех и часто не нужно
Причина того, что семантика загрузки-получения и освобождения магазина реализована в терминах барьеров LoadLoad, LoadStore и StoreStore, заключается в том, что ISA предоставляют только такие барьеры. Существуют предложения по исследованию более гибких или настраиваемых барьеров, которые могут применяться только к конкретным операциям с памятью или диапазону или блоку инструкций, но они еще не пробились ни к одному из ISA.