Многое из этого было рассмотрено в других вопросах и ответах, но здесь я приведу краткое изложение.(И искать ссылки для добавления).Тем не менее, хороший вопрос, полезно собрать все это в одном месте.
На x86 каждая нагрузка asm является загрузочной загрузкой .Чтобы реализовать это эффективно, современные x86 HW спекулятивно загружаются раньше, чем разрешено, а затем проверяют это предположение.(Потенциально может привести к возникновению ошибки в конвейере неправильной спекуляции порядка памяти.) Чтобы отслеживать это, Intel называет комбинацию буферов загрузки и хранения «Буфер порядка памяти».
Слабо упорядоченные ISA не должныПредположим, что они могут просто загружаться в любом порядке.
Порядок хранения в x86 поддерживается только разрешением сохранения хранилищ из буфера хранилища в L1d в программном порядке.
По крайней мере, на процессорах Intel запись буфера хранилища выделяется для хранилища при его выдаче (из внешнего интерфейса в ROB + RS).У всех мопов должна быть выделена запись ROB для них, но у некоторых мопов также должны быть выделены другие ресурсы, такие как записи буфера загрузки или хранения, RAT-записи для регистров, которые они читают / записывают и т. Д.
Так что я думаю, что сам буфер хранилища заказан .Когда выполняется сохранение адреса хранилища или данных хранилища, оно просто записывает адрес или данные в свою уже выделенную запись буфера хранилища.Поскольку commit (освобождение записей SB) и allocate расположены в программном порядке, я предполагаю, что это физически круговой буфер с головой и хвостом, как ROB.(И в отличие от RS).
Отказ от LoadStore в основном бесплатен : загрузка не может быть снята до тех пор, пока она не будет выполнена (данные взяты из кэша).Магазин не может совершать операции до после , когда он закрывается.Изъятие по порядку автоматически означает, что все предыдущие загрузки выполняются до того, как магазин «градуирован» и готов к фиксации.
Слабо упорядоченный uarch, который на практике может выполнять переупорядочивание хранилища, может загружать табло: пусть ониУйдите в отставку, как только они не будут исправны, но до того, как данные поступят.
Это кажется более вероятным для ядра в порядке, но IDK.Таким образом, вы можете получить загрузку, которая будет удалена, но место назначения регистра все равно остановится, если что-то попытается прочитать его до того, как данные действительно поступят.Мы знаем, что обычные ядра на практике работают таким образом, не требуя загрузки до завершения , прежде чем последующие инструкции могут быть выполнены.(Вот почему программная конвейерная обработка с использованием большого количества регистров так ценна на таких ядрах, например, для реализации memcpy. Считывание результата загрузки сразу на упорядоченном ядре разрушает параллелизм памяти.)
Каквозможно ли переупорядочение load-> store с фиксацией по порядку? углубляется в этот порядок, по порядку или вне очереди.
Инструкции барьера
Единственная барьерная инструкция, которая делает что-либо для обычных хранилищ, - это mfence
, которая на практике останавливает операции памяти (или весь конвейер) до тех пор, пока буфер хранилища не будет очищен. Является ли загрузка и хранение единственной инструкцией, которая переупорядочивается? охватывает поведение Skylake-с-обновленным микрокодом, действующее как lfence
.
lfence
в основном существует для микроархитектурыэффект блокирования более поздних инструкций даже от выдачи до тех пор, пока все предыдущие инструкции не вышли из вышедшего из строя бэк-энда (удалились).Варианты использования lfence
для упорядочения памяти практически отсутствуют.
относящиеся:
- Сколько инструкций по барьерам памяти имеет процессор x86?
- Как я могу увидеть, что "LFENCE или SFENCE не могут пройти ранее чтение / запись"
- Имеет ли блокировка xchg то же поведение, что и mfence?
- Делает ли модель памяти Intel избыточность SFENCE и LFENCE?
- Понимание влияния lfence на цикл с двумя длинными цепочками зависимостей для увеличения длины подробно расскажет о том, как LFENCE останавливает выполнение более поздних инструкций, и что это означает для производительности.
- Когда я должен использовать _mm_sfence _mm_lfence и _mm_mfence языки высокого уровня имеют более слабые модели памяти, чем x86, поэтому иногда вам нужен только барьер, который компилируется без инструкций asm.Использование
_mm_sfence()
, когда вы не использовали NT-хранилища, просто делает ваш код медленнее без причины, чем atomic_thread_fence(mo_release)
.