Является ли барьер памяти инструкцией, которую выполняет CPU, или это просто маркер?

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

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

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

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

inst1
store1
inst2
load1
inst3
mfence
inst4
store2
load2
inst5

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

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

Ответ 3

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 <[email protected]>
 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/Обратите внимание на то, что в строке mfence есть команда (3 бита) (0f ae f0)

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

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

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


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

Ответ 4

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

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

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