Барьер памяти - это инструкция, которую выполняет процессор, или это просто маркер?

Я пытаюсь понять, что именно является барьером памяти. На основании того, что я знаю до сих пор, барьер памяти (например: mfence) используется для предотвращения переупорядочения инструкций с до до и после и после до перед барьером памяти.

Это пример использования барьера памяти:

instruction 1
instruction 2
instruction 3
mfence
instruction 4
instruction 5
instruction 6

Теперь мой вопрос: mfence инструкция просто маркер, указывающий процессору в каком порядке выполнять инструкции? Или это инструкция, которую ЦП фактически выполняет так же, как выполняет другие инструкции (например: mov).

4 ответа

Каждая последовательность байтов, которую ЦПУ встречает среди своего кода, является инструкцией, которую ЦПУ выполняет. Других видов инструкций нет.

Это ясно видно как в справочнике по инструкциям Intel, так и на специальной странице для mfence.

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

Инструкция MFENCE упорядочена в отношении всех инструкций загрузки и хранения, других инструкций MFENCE, любых инструкций LFENCE и SFENCE и любых инструкций сериализации (таких как инструкция CPUID). MFENCE не сериализует поток команд. Слабо упорядоченные типы памяти могут использоваться для достижения более высокой производительности процессора с помощью таких методов, как проблема неупорядоченности, умозрительное чтение, объединение записи и сжатие записи. Степень, в которой потребитель данных распознает или знает, что данные слабо упорядочены, варьируется в зависимости от приложений и может быть неизвестна производителю этих данных. Инструкция MFENCE обеспечивает эффективный способ обеспечения упорядочения загрузки и хранения между подпрограммами, которые дают результаты со слабым упорядочением, и подпрограммами, которые потребляют эти данные.

Процессоры могут произвольно извлекать и кэшировать данные из областей системной памяти, которые используют типы памяти WB, WC и WT. Эта умозрительная выборка может происходить в любое время и не связана с выполнением инструкции. Таким образом, он не упорядочен в отношении выполнения инструкции MFENCE; данные могут быть введены в кэш спекулятивно непосредственно перед, во время или после выполнения инструкции MFENCE.

Как вы можете видеть из выдержки MFence инструкция выполняет довольно много работы, а не просто является своего рода маркером.

Я объясню влияние, которое mfence имеет на потоке трубопровода. Рассмотрим трубопровод Skylake, например. Рассмотрим следующую последовательность инструкций:

inst1
store1
inst2
load1
inst3
mfence
inst4
store2
load2
inst5

Инструкции декодируются в последовательность мопов в том же порядке программы. Затем все мопы передаются в планировщик. Обычно без заборов все мопы выдаются для выполнения вне очереди. Однако, когда планировщик получает mfence моп, нужно убедиться, что нет мопов памяти mfence выполняются до тех пор, пока все входящие операции памяти не станут глобально видимыми (что означает, что хранилища были удалены, а загрузки по крайней мере завершены). Это относится ко всем обращениям к памяти независимо от типа памяти региона, к которому осуществляется доступ. Это может быть достигнуто либо с помощью планировщика, чтобы он не выдавал какое-либо нижестоящее хранилище, либо не загружал мопы в хранилище, либо не загружал буферы, соответственно, до тех пор, пока буферы не опустошаются, либо путем выдачи нисходящего хранилища или загрузочных мопов и маркировки их, чтобы их можно было отличить от все существующие в памяти буферы. Все мёртвые, не связанные с памятью, выше или ниже ограждения могут быть выполнены не по порядку. В примере один раз store1 уходит в отставку и load1 завершает (получая данные и удерживая их в каком-то внутреннем регистре), mfence Инструкция считается выполненной. я думаю что mfence может занимать или не занимать какие-либо ресурсы в бэкэнде (ROB или RS), и он может быть переведен более чем в один моп.

Intel имеет патент, представленный в 1999 году, который описывает, как mfence работает. Поскольку это очень старый патент, реализация может измениться или может отличаться в разных процессорах. Я суммирую патент здесь. mfence раскодируется в три мопа. К сожалению, не совсем понятно, для чего используются эти мопы. Затем записи распределяются от станции резервирования, распределяются для хранения мопов, а также распределяются из буферов загрузки и хранения. Это означает, что в буфере загрузки могут храниться записи либо для истинных запросов на загрузку, либо для ограждений (которые в основном являются поддельными запросами на загрузку). Аналогично, буфер хранилища может содержать записи для истинных запросов хранилища и для заборов. mfence uop не отправляется до тех пор, пока все предыдущие загрузки или сохранения (в соответствующих буферах) не будут удалены. Когда это произойдет, mfence Сам uop отправляется на контроллер кэша L1 в качестве запроса памяти. Контроллер проверяет, все ли предыдущие запросы выполнены. В этом случае он будет просто рассматриваться как NOP, а моп получит покрытие из буферов. В противном случае контроллер кэша отклоняет mfence моп.

mfence это инструкция.

Чтобы получить это на Linux:

1 / Написать файл mfence.c

#include <stdio.h>

int main(){
    printf("Disass me\n");
    asm volatile ("mfence" ::: "memory");
    return 0;
}

2 / Компилировать

gcc mfence.c mfence

3/ Разобрать

objdump -d mfence | grep -A 10 "<main>:"

000000000000063a <main>:
 63a:   55                      push   %rbp
 63b:   48 89 e5                mov    %rsp,%rbp
 63e:   48 8d 3d 9f 00 00 00    lea    0x9f(%rip),%rdi        # 6e4 <_IO_stdin_used+0x4>
 645:   e8 c6 fe ff ff          callq  510 <puts@plt>
 64a:   0f ae f0                mfence 
 64d:   b8 00 00 00 00          mov    $0x0,%eax
 652:   5d                      pop    %rbp
 653:   c3                      retq   
 654:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 65b:   00 00 00 

4/ Заметьте, что в строке 64а mfence это (3 бита) инструкция (0f ae f0)

Так что это инструкция процессора (как mov): Процессору необходимо декодировать предыдущие инструкции, прежде чем перейти к нему, иначе он не сможет угадать его выравнивание.

Например 0f ae f0 может появиться в адресе, поэтому процессор не может использовать его в качестве создателя.

Наконец, это просто инструкция старой школы, и в точке ее выполнения в конвейере она будет синхронизировать доступ к памяти в дальнейшем в конвейере перед выполнением следующей инструкции.


Примечание: в Windows используйте макрос _ReadWriteBarrier чтобы произвести оборону

Ваш вопрос имеет неверные предположения. MFENCE не препятствует переупорядочению инструкций (см. Выделенную цитату). Например, если имеется поток из 1000 инструкций, которые работают только с регистрами, а инструкция MFENCE размещена посередине, это не повлияет на то, как ЦП переупорядочивает эти инструкции.

Инструкция MFENCE упорядочена в отношении всех инструкций загрузки и хранения, других инструкций MFENCE, любых инструкций LFENCE и SFENCE и любых инструкций сериализации (таких как инструкция CPUID). MFENCE не сериализует поток команд.

Вместо этого инструкция MFENCE предотвращает переупорядочение загрузок и сохраняет их в кэш-памяти и основной памяти.

Другие вопросы по тегам