Является ли барьер памяти инструкцией, которую выполняет 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 предотвращает переупорядочение нагрузок и хранилищ в кеш и основную память.