Я объясню влияние, которое mfence
оказывает на поток в конвейере. Рассмотрим, например, конвейер Skylake. Рассмотрим следующую последовательность инструкций:
inst1
store1
inst2
load1
inst3
mfence
inst4
store2
load2
inst5
Инструкции декодируются в последовательность операций в одном и том же программном порядке. Затем все ошибки передаются планировщику. Обычно без ограждений все мопы выдаются на исполнение вне очереди. Однако, когда планировщик получает mfence
uop, он должен убедиться, что никакие мопы памяти ниже по потоку mfence
не выполняются до тех пор, пока все восходящие мопы памяти не станут глобально видимыми (что означает, что хранилища удалены и загрузка по крайней мере завершена). Это относится ко всем доступам к памяти независимо от типа памяти области, к которой осуществляется доступ. Это может быть достигнуто либо планировщиком, чтобы он не выдавал какие-либо нижестоящие операторы хранилища или загрузку мопов в хранилище или загрузочные буферы, соответственно, до тех пор, пока буферы не будут исчерпаны, либо путем выдачи нижестоящих операций сохранения или загрузки и их маркировки, чтобы их можно было отличить от все существующие ошибки памяти в буферах. Все мопы, не связанные с памятью, выше или ниже забора могут выполняться вне очереди. В этом примере, когда store1
удаляется и load1
завершается (получая данные и удерживая их в каком-то внутреннем регистре), инструкция mfence
считается завершенной. Я думаю, что mfence
может или не может занимать какие-либо ресурсы в бэкэнде (ROB или RS), и он может быть переведен более чем на один uop.
У Intel есть патент, поданный в 1999 г., в котором описывается, как работает mfence
. Поскольку это очень старый патент, реализация может быть изменена или может отличаться в разных процессорах. Я резюмирую здесь патент. mfence
декодируется на три мопса. К сожалению, не совсем ясно, для чего используются эти мопы. Затем записи выделяются из станции резервирования, которая выделяется для хранения мопов, а также выделяется из буферов загрузки и хранения. Это означает, что буфер загрузки может содержать записи либо для истинных запросов нагрузки, либо для ограждений (которые в основном являются ложными запросами на загрузку). Точно так же буфер хранилища может содержать записи для истинных запросов хранилища и для ограждений. mfence
uop не отправляется до тех пор, пока все предыдущие операции загрузки или сохранения (в соответствующих буферах) не будут удалены. Когда это происходит, сама mfence
uop отправляется контроллеру кеш-памяти L1 как запрос памяти. Контроллер проверяет, выполнены ли все предыдущие запросы. В этом случае он будет просто обрабатываться как NOP, и uop будет удален из буферов. В противном случае контроллер кеша отклоняет mfence
uop.
person
Hadi Brais
schedule
11.05.2018
std::atomic_signal_fence()
или GNU Casm("":::"memory")
, являются просто маркерами в исходном коде и компилируются с нулевыми инструкциями. Они существуют для блокировки переупорядочения во время компиляции и особенно полезны, когда целевая архитектура имеет более сильную модель памяти, чем исходный язык (например, C ++ - ›x86 asm). preshing.com/20120625/memory-ordering-at-compile-time объясняет больше. - person Peter Cordes   schedule 11.05.2018