Из-за исполнения заказа и забора памяти

Я знаю, что современные процессоры могут выполнять не по порядку, но они всегда удаляют результаты в порядке, как описано в wikipedia.

"Из процессоров Oder эти" слоты "засыпают вовремя другими готовыми инструкциями, , а затем повторно заказывайте результаты в конце, чтобы убедиться, что инструкции обработаны как обычно."

Теперь, когда говорят о необходимости использования многоядерных платформ, требуется память, потому что из-за выполнения Out of Order здесь может быть напечатано неправильное значение x.

Processor #1:
 while f == 0
  ;
 print x; // x might not be 42 here

Processor #2:
 x = 42;
 // Memory fence required here
 f = 1

Теперь мой вопрос заключается в том, что, поскольку процессоры Out of Order (ядра в случае процессоров MultiCore, которые, как я полагаю), всегда удаляют результаты In-Order, то в чем же необходимость заборов памяти. Не следует ли, чтобы ядра многоядерного процессора видели результаты, удаленные от других ядер, или они также видят результаты, которые находятся в полете?

Я имею в виду в приведенном выше примере, когда процессор 2 в конечном итоге удалит результаты, результат x должен превышать f, правильно? Я знаю, что во время выполнения вне порядка он мог бы изменить f до x, но он, возможно, не удалил его до x, правильно?

Теперь, когда у вас есть возможность возврата в исходное состояние и механизм когерентности кэша, зачем вам понадобится память в x86?

Ответ 1

В этом руководстве объясняются проблемы: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

FWIW, где проблемы с упорядочением памяти происходят на современных процессорах x86, причина в том, что, хотя модель согласованности памяти x86 предлагает довольно сильную согласованность, необходимы явные барьеры для обеспечения согласованности после чтения. Это связано с тем, что называется "буфер хранения".

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

store x
load y

то на процессорной шине это можно увидеть как

load y
store x

Причиной такого поведения является вышеупомянутый буфер хранилища, который является небольшим буфером для записи до того, как они выходят на системную шину. Задержка загрузки - это OTOH, критическая проблема для производительности, и, следовательно, нагрузкам разрешено "переходить в очередь".

См. раздел 8.2 в http://download.intel.com/design/processor/manuals/253668.pdf

Ответ 2

Запоминание памяти гарантирует, что все изменения переменных перед ограждением видны для всех других ядер, так что все ядра имеют обновленное представление данных.

Если вы не поместите забор памяти, ядра могут работать с неправильными данными, это можно увидеть особенно в сценариях, где несколько ядер будут работать с одними и теми же наборами данных. В этом случае вы можете убедиться, что когда CPU 0 совершил какое-либо действие, все изменения, сделанные в наборе данных, теперь видны всем другим ядрам, которые затем могут работать с актуальной информацией.

Некоторые архитектуры, включая вездесущие x86/x64, предоставляют несколько инструкции по защите памяти, включая инструкцию, иногда называемую "полный забор". Полный забор гарантирует, что все операции загрузки и хранения до того, как забор будет зафиксирован до любых нагрузок и магазины, выпущенные после ограждения.

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

Ключ находится в буфере хранения, который находится между кешем и ЦП, и делает следующее:

Хранить буфер, невидимый для удаленных ЦП

Хранить буфер позволяет записывать в память и/или кеши для сохранения в оптимизировать доступ к межсетевым соединениям

Это означает, что все вещи будут записаны в этот буфер, а затем в какой-то момент буфер будет записан в кеш. Таким образом, кеш может содержать представление данных, которое не является самым последним, и, следовательно, другой ЦП, благодаря когерентности кеша, также не будет иметь последних данных. Для того, чтобы последние данные были видимыми, необходим флеш-накопитель для хранилища, это, по-моему, по сути является тем, что забор памяти будет происходить на аппаратном уровне.

EDIT:

Для кода, который вы использовали в качестве примера, Wikipedia говорит следующее:

Покрытие памяти может быть вставлено перед назначением процессора # 2 в f чтобы новое значение x было видимым для других процессоров на до изменения значения f.

Ответ 3

Просто, чтобы четко указать, что неявно в предыдущих ответах, это правильно, но отличается от доступа к памяти:

Процессоры могут выполняться не в порядке, но они всегда удаляют результаты в порядке

Отставка инструкции отделена от выполнения доступа к памяти, доступ к памяти может завершиться в другое время до выхода на пенсию.

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

(В x86 и ARM я думаю, что только магазины, вероятно, подчиняются этому, но, например, Alpha может загружать старое значение из памяти. x86 SSE2 имеет инструкции с более слабыми guarentees, чем обычное поведение x86).

PS. Из памяти заброшенный Sparc ROCK мог на самом деле уйти в отставку из-за порядка, он потратил энергию и транзисторы, определяя, когда это было безвредно. Он был оставлен из-за потребления энергии и количества транзисторов... Я не считаю, что какой-либо CPU общего назначения был куплен на рынок с выходом из строя вне очереди.