2015-09-21 8 views
13

В Intel Модель памяти гарантирует:Имеет ли модель памяти Intel избыточность и LFENCE?

  • магазины не будут переупорядочен с другими Stores
  • Грузы не будет повторно заказанные с другими нагрузками

http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/

У меня есть что SFENCE избыточно на x86-64 из-за модели памяти Intel, но никогда не LFENCE. Выполняют ли указанные выше правила модели памяти либо избыточные инструкции?

+0

Err, как насчет заказа на склад и загрузку? –

+0

@IwillnotexistIdonotexist: MFENCE - это барьер StoreLoad (и все три других типа). И да, вы все еще нуждаетесь в этом. : P Я не уверен, что movNT load/stores может показать переупорядочение LoadStore или если они опустили отдельную инструкцию по блокировке LoadStore в предположении, что вам обычно (всегда?) Нужен барьер StoreLoad в любое время, когда вам нужен барьер LoadStore. Так как это влияет только на movnt streaming ops, это частный случай специального случая, а x86 - без него. : P –

+0

@PeterCordes [В предыдущем ответе] (http://stackoverflow.com/a/22142537/2809095) я привел полный список или разрешенные переупорядочивания из SDM Intel. Но то, во что я ехал с моим комментарием выше, - это то, что OP указывал, в основном, правильно, что переупорядочение загрузки и загрузки магазина не происходит. Тем не менее, это всего лишь две из четырех возможностей (Load-Store и Store-Load - две другие комбинации), а также другие возможности _can_, откуда возникает необходимость в «mfence/sfence/lfence». –

ответ

12

Да, SFENCE и LFENCE не являются операционными системами, за исключением случаев, когда используются потоковые хранилища movnt (Non-Temporal) или работают с областями памяти с типом, установленным на нечто иное, чем нормальное Write-Back. Хранилища NT обходят кеш, а также слабо упорядочиваются (но x86's normal memory model is strongly ordered (за исключением приведенных ниже для опций Fast-String)). (NT загружает (movntdqa) из памяти WB still strongly ordered, поэтому LFENCE полезен только при чтении из слабоупорядоченной памяти). Это происходит не случайно в «нормальных» программах, поэтому вам нужно только беспокоиться об этом, если вы mmap видеопамять или что-то в этом роде.

Этот пост: Memory Reordering Caught in the Act - это более легкое для чтения описание того же случая, о котором говорит сообщение Бартоша, где вам нужен барьер StoreLoad, такой как MFENCE.

Если у вас возникли вопросы после прочтения этой ссылки, вы опубликовали сообщения в блоге Джеффа Прешинга. Они дали мне хорошее представление о предмете. :) Хотя я думаю, что я нашел лакомый кусочек о том, что SFENCE/LFENCE обычно не является операцией на странице Дуга Ли. Сообщения Джеффа не рассматривали загрузки/хранилища NT.


мне было любопытно об этом пару недель назад, и отправил довольно подробный ответ на недавний вопрос: Atomic operations, std::atomic<> and ordering of writes. Я включил множество ссылок на материал о модели памяти моделей C++ и аппаратной памяти.

Если вы пишете на C++, использование std::atomic<> - отличный способ рассказать компилятору, какие у вас требования к заказу, поэтому он не переупорядочивает ваши операции с памятью во время компиляции. Вы можете и должны использовать более слабый выпуск или приобретать семантику, где это необходимо, вместо последовательной согласованности по умолчанию, поэтому компилятору вообще не нужно выводить какие-либо барьерные инструкции на x86. Он просто должен поддерживать ops в исходном порядке.


На слабо упорядоченной архитектуры, как ARM или PPC или x86 с movnt, вам нужна инструкция StoreStore барьера между написанием буфера и установив флаг, чтобы указать, что данные готовы. Кроме того, читателю нужна инструкция по загрузке LoadLoad между проверкой флага и чтением буфера.

Не считая movnt, x86 уже имеет барьеры LoadLoad между каждой нагрузкой и барьеры StoreStore между каждым магазином. (Заказ LoadStore также гарантирован). MFENCE - все 4 вида барьеров, включая StoreLoad, который является единственным барьером x86 по умолчанию. MFENCE гарантирует, что нагрузки не будут использовать старые предварительно выбранные значения до того, как другие потоки увидели ваши магазины и, возможно, сделают собственные магазины. (Также как барьер для заказа магазина и заказа на загрузку).

Удовлетворительный факт: x86 lock -предоставляемые инструкции также являются полными барьерами памяти. Они могут использоваться в качестве замены для MFENCE в старом 32-битном коде, который может работать на процессорах, не поддерживающих его.lock add [esp], 0 в противном случае не работает, и цикл чтения/изменения/записи в памяти очень важен в кеше L1 и уже находится в состоянии M протокола согласования MESI.

SFENCE - это бар StoreStore.

LFENCE - это LoadLoad и also a LoadStore barrier. (loadNT/LFENCE/storeNT предотвращает магазин стать видимыми глобально перед нагрузкой. Я думаю, что это может произойти на практике, если адрес загрузки был результатом длинной цепи зависимостей, или в результате другой нагрузки, пропущенной в кэше.)


Забавный факт # 2 (спасибо @EOF): Магазины из Fast-String Ops (rep stosb/rep movsb на IvyBridge и позже) являются слабоупорядоченными (но не кэширующими).

Intel документирует тот факт, что Fast-String Ops «может показаться неработоспособным» в разделе 7.3.9.3 Руководства для разработчиков ПО, vol1. Они также говорят,

«Order-зависимый код должен написать дискретный переменный семафор после любых операций со строками, чтобы правильно разрешить упорядоченным данные следует рассматривать всех процессорами»

Они не упоминают любые барьерные инструкции. То, как я его читал, есть неявное СФЕРА после rep stosb/rep movsb (по крайней мере, забор для строковых данных, возможно, не для другого слабого заказанного в полете NT). Во всяком случае, формулировка подразумевает, что запись в флаг/семафор становится глобально видимой после вся строка-перемещение записывает, поэтому в коде, который заполняет буфер операцией fast string, а затем записывает флаг, не требуется SFENCE/LFENCE , или в коде, который его читает. (Заказ LoadLoad всегда происходит, поэтому вы всегда видите данные в том порядке, в котором другие ЦП сделали его глобально видимым, т. Е. Использование слабо упорядоченных магазинов для записи буфера не меняет того факта, что нагрузки в других потоках по-прежнему сильно упорядочены.)

summary: используйте обычный магазин, чтобы записать флаг, указывающий, что буфер готов. У читателей не проверяется последний байт блока, написанный с помощью memset/memcpy. Тем не менее, я думаю, что магазины быстрой строки не позволяют каким-либо более поздним хранилищам передавать их, поэтому вам все равно нужен только SFENCE/LFENCE, если вы используете movNT.

Существует бит процессора MSR, который можно очистить, чтобы отключить операторы быстрой строки, в интересах новых серверов, которым необходимо запустить старые двоичные файлы, которые записывают флаг «данные готовятся» как часть rep stosb или rep movsb.

+3

Это не только 'movnt', у которого более слабый порядок памяти. Команды memcpy/strcpy ('rep [ne] movs [b/w/d/q]') тоже. – EOF

+0

@EOF: Спасибо, я этого не знал! Странно, что в руководстве insn ref не упоминается об этом, только в руководстве Vol1. Я обновил свой ответ с моей интерпретацией того, что говорят документы: существует неявный барьер StoreStore (для строковых данных) после 'rep movsb', поэтому вам просто нужно отдельно записать флаг готовности к данным (а не как последние байты строка op). –

+0

@EOF: Это не только 'movnt' и' rep [ne] movs [b/w/d/q] '; но (потенциально) каждую отдельную инструкцию, которая обращается к памяти; учитывая, что модель упорядочения памяти может быть ослаблена путем настройки таблиц PAT/page или MTRR для доступа к памяти в качестве «комбинирования записи» (а не «записи назад»). – Brendan