Инструкции по переупорядочению процессора x86? - PullRequest
0 голосов
/ 12 мая 2018

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

Чтобы решить проблему переупорядочения инструкций, мы можем вставить барьеры памяти в соответствующие места в коде.

Но инструкции по переупорядочению процессора x86? Если это не так, то нет необходимости использовать барьеры памяти, верно?

1 Ответ

0 голосов
/ 12 мая 2018

1001 * Изменение порядка * Да, все современные чипы x86 от Intel и AMD настойчиво переупорядочивают инструкции в окне, которое имеет глубину около 200 команд для последних процессоров обоих производителей (то есть новая инструкция может выполняться, в то время как более старая инструкция в прошлом выполняла более 200 команд) "все еще ждет". Как правило, все это невидимо для одного потока, поскольку ЦП все еще поддерживает иллюзию последовательного выполнения 1 текущим потоком, уважая зависимости, поэтому с точки зрения текущего потока выполнения это если инструкции выполнялись последовательно. Барьеры памяти

Это должно ответить на главный вопрос, но тогда ваш второй вопрос о барьерах памяти. Однако в нем содержится неверное предположение о том, что перестановка инструкция обязательно вызывает (и является единственной причиной) видимое переупорядочение memory . На самом деле, переупорядочение команд не является ни достаточным, ни необходимым для переупорядочения памяти между потоками.

Теперь, безусловно, верно, что выполнение вне очереди - это основной драйвер возможностей доступа из памяти вне порядка, или, возможно, это квест для MLP (параллелизм на уровне памяти) ) , которая обеспечивает все более мощные возможности выхода из строя для современных процессоров. На самом деле, оба, вероятно, верны сразу: растущие возможности выхода из строя много выигрывают от сильных возможностей переупорядочения памяти, и в то же время агрессивное переупорядочение и перекрытие памяти невозможно без хороших возможностей выхода из строя, поэтому они помогают друг другу в виде самоусиливающейся петли типа «сумма больше чем часть».

Так что да, неправильное выполнение и переупорядочение памяти, безусловно, имеют отношения; тем не менее, вы можете легко получить повторный заказ без выполнения не по порядку ! Например, буфер основного локального хранилища часто вызывает явное переупорядочение: в момент выполнения хранилище не записывается непосредственно в кэш (и, следовательно, не отображается в точке когерентности), что задерживает локальные хранилища по отношению к локальным загружает, которые должны прочитать их значения в точке выполнения.

Как Питер также указывает в ветке комментариев , вы также можете получить тип переупорядочения нагрузки-нагрузки, когда нагрузкам разрешено перекрываться в заказе в порядке: нагрузка 1 может запуск , но при отсутствии команды, потребляющей свой результат, конвейерная конструкция порядка может перейти к следующим инструкциям, которые могут включать в себя еще одну загрузку 2. Если загрузка 2 является попаданием в кэш, а загрузка 1 была пропуском кеша, загрузка 2 может быть выполнено раньше по времени от нагрузки 1, и, следовательно, видимый порядок может быть заменен на новый.

Итак, мы видим, что не все переупорядочение памяти между потоками вызвано переупорядочением команд, но определенное переупорядочение команд также подразумевает неупорядоченную память доступ, верно? Нет так быстро! Здесь есть два разных контекста: что происходит на аппаратном уровне (т. Е. Могут ли инструкции по доступу к памяти, на практике, выполняться не по порядку) и что гарантируется документацией ISA и платформы (часто называемой модель памяти применима к аппаратному обеспечению).

x86 повторный заказ

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

В то же время x86 определяет довольно строгую модель памяти, которая запрещает большинство возможных переупорядочений, грубо говоря, следующим образом:

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

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

Ну, x86 выполняет кучу дополнительной работы, чтобы точно отследить первоначальный порядок загрузки и хранения, и гарантирует, что никакие переупорядочения памяти, которые нарушают правила, никогда не будут видны. Например, допустим, что загрузка 2 выполняется перед загрузкой 1 (загрузка 1 появляется раньше в программном порядке), но обе задействованные строки кэша находились в состоянии «эксклюзивного владения» в течение периода, когда выполнялась загрузка 1 и загрузка 2: произошла переупорядочение , но локальное ядро ​​знает, что его нельзя наблюдать , потому что никто другой не смог заглянуть в эту локальную операцию.

В сочетании с вышеупомянутыми оптимизациями ЦП также используют умозрительное выполнение: выполняют все не по порядку, даже если возможно, что в какой-то более поздний момент какое-то ядро ​​сможет заметить разницу, но на самом деле не commit инструкции до такого наблюдения невозможны. Если такое наблюдение действительно происходит, вы откатываете процессор до более раннего состояния и попробуйте снова. Это является причиной «очистки машины для упорядочивания памяти» в Intel.

Таким образом, можно определить ISA, который не позволяет любой переупорядочивать вообще, но под крышками переупорядочивать, но тщательно проверять, что это не наблюдается. PA-RISC является примером такой последовательно согласованной архитектуры. Intel обладает сильной моделью памяти, которая допускает один тип переупорядочения, но запрещает многие другие, но каждый чип внутри может делать больше (или меньше) переупорядочения, если они могут гарантировать игру по правилам в наблюдаемом смысле (в этом в некотором смысле, это связано с правилом «как будто», которым руководствуются компиляторы, когда речь заходит об оптимизации).

Результатом всего этого является то, что да , x86 требует барьеров памяти для предотвращения, в частности, так называемого переупорядочения StoreLoad (для алгоритмов, которые требуют эту гарантию). В x86 вы не найдете много отдельных барьеров памяти на практике, потому что большинству параллельных алгоритмов также необходимы операции atomic , такие как атомарное добавление, тестирование и установка или сравнение и обмен, а в x86 - все идут с полными барьерами бесплатно. Поэтому использование явных инструкций барьера памяти, таких как mfence, ограничено случаями, когда вы не выполняете атомарную операцию чтения-изменения-записи.

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


1 Конечно, если вы приложите достаточно усилий, такое переупорядочение будет видно! Ярким последним примером этого могут служить эксплойты Spectre и Meltdown, которые используют спекулятивное неупорядоченное выполнение и побочный канал кэша для нарушения границ безопасности защиты памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...