Заборы исполнения и памяти

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

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

Теперь говорят, что для использования многоядерных платформ требуются ограждения памяти, потому что из-за выполнения 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 (ядра в случае многоядерных процессоров, я полагаю) всегда удаляют результаты In-Order, тогда зачем нужны заборы памяти. Разве ядра многоядерного процессора не видят результаты, удаленные только из других ядер, или они также видят результаты, которые находятся в полете?

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

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

3 ответа

Решение

В этом руководстве рассматриваются следующие проблемы: 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

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

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

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

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

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

Хранить буфер невидимым для удаленных процессоров

Буфер хранения позволяет сохранять записи в память и / или кэш-память для оптимизации доступа к межсоединениям.

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

РЕДАКТИРОВАТЬ:

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

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

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

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

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

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

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

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

Другие вопросы по тегам