Устранение неоднозначности в памяти - Memory disambiguation

Устранение неоднозначности в памяти это набор методов, используемых высокопроизводительными внеочередное исполнение микропроцессоры которые выполняют объем памяти доступ инструкции (загружает и сохраняет) вне программы. Механизмы устранения неоднозначности памяти, реализованные с использованием цифровая логика внутри ядра микропроцессора обнаруживает истинные зависимости между операциями с памятью во время выполнения и позволяет процессору восстанавливаться, когда зависимость была нарушена. Они также устраняют ложные зависимости от памяти и позволяют параллелизм на уровне инструкций обеспечивая безопасное выполнение грузов и складов вне очереди.

Фон

Зависимости

При попытке выполнить инструкции не по порядку микропроцессор должен учитывать истинные зависимости между инструкции. Например, рассмотрим простую истинную зависимость:

1: добавить $ 1, $ 2, $ 3 # R1 <= R2 + R32: добавить $ 5, $ 1, $ 4 # R5 <= R1 + R4 (зависит от 1)

В этом примере Добавить инструкция в строке 2 зависит от Добавить инструкция в строке 1, потому что регистр R1 - источник операнд операции сложения в строке 2. Добавить в строке 2 не может выполняться, пока Добавить на строке 1 завершается. В этом случае зависимость имеет вид статический и легко определяется микропроцессором, потому что источники и назначения являются регистрами. Регистр назначения Добавить инструкция в строке 1 (R1) является частью кодирования инструкций и поэтому может быть определен микропроцессором на ранней стадии, на этапе декодирования конвейера. Точно так же исходные регистры Добавить инструкция в строке 2 (R1 и R4) также кодируются в самой инструкции и определяются при декодировании. Чтобы соблюдать эту истинную зависимость, логика планировщика микропроцессора будет выдавать эти инструкции в правильном порядке (сначала инструкция 1, затем инструкция 2), так что результаты 1 будут доступны, когда они потребуются инструкции 2.

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

1: сохранить $ 1, 2 ($ 2) # Mem [R2 + 2] <= R12: загрузить $ 3, 4 ($ 4) # R3 <= Mem [R4 + 4] (возможно, зависит от 1, возможен тот же адрес, что и выше)

Здесь инструкция сохранения записывает значение в ячейку памяти, указанную значением в адресе (R2 + 2), а инструкция загрузки считывает значение в ячейке памяти, указанной значением в адресе (R4 + 4). Микропроцессор не может статически определить перед выполнением, являются ли ячейки памяти, указанные в этих двух инструкциях, разными или одинаковыми, поскольку эти ячейки зависят от значений в R2 и R4. Если расположение отличается, инструкции независимы и могут успешно выполняться вне очереди. Однако, если местоположения совпадают, то инструкция загрузки зависит от хранилища для получения своего значения. Это известно как неоднозначная зависимость.

Выполнение вне очереди и операции доступа к памяти

Выполнение загрузок и сохранений не по порядку может привести к неверным результатам, если зависимая пара загрузка / сохранение была выполнена не по порядку. Рассмотрим следующий фрагмент кода, приведенный в MIPS сборка:

1: div 27 долларов, 202 доллара: 27 долларов США, 0 (30 долларов) 3: lw 08 долларов США, 0 (31 доллар США) 4: 26 долларов США, 0 (30 долларов США) 5: lw 09 долларов США, 0 (31 доллар США)

Предположим, что логика планирования выдаст команду исполнительному блоку, когда все его операнды регистра будут готовы. Далее предположим, что регистры $30 и $31 готовы: ценности в $30 и $31 были вычислены очень давно и не изменились. Однако предположим $27 не готов: его значение все еще вычисляется div (целочисленное деление) инструкция. Наконец, предположим, что регистры $30 и $31 содержат одно и то же значение, и, таким образом, все загрузки и сохранения в сниппете обращаются к одному и тому же слову памяти.

В этой ситуации 27 евро, 0 (30 долларов) инструкция в строке 2 не готова к выполнению, но lw $ 08, 0 (31 $) инструкция в строке 3 готова. Если процессор позволяет lw инструкция выполнить до sw, загрузка прочитает старое значение из системы памяти; однако он должен был прочитать значение, которое только что было записано sw. Загрузка и сохранение выполнялись вне программного порядка, но между ними была нарушена зависимость памяти.

Аналогично предположим, что регистр $26 является готовы. В 26,00 швейцарских долларов (30 долларов) инструкция в строке 4 также готова к выполнению, и она может выполняться перед предыдущим lw $ 08, 0 (31 $) в строке 3. Если это произойдет, lw $ 08, 0 (31 $) инструкция будет читать неправильный значение из системы памяти, так как более поздняя инструкция сохранения записала свое значение туда до выполнения загрузки.

Характеристика зависимостей памяти

Зависимости памяти бывают трех видов:

  • Чтение после записи (RAW) зависимости: также известные как истинные зависимости, зависимости RAW возникают, когда операция загрузки считывает из памяти значение, которое было создано последней предыдущей операцией сохранения по тому же адресу.
  • Запись после чтения (WAR) зависимости: также известные как анти-зависимости, WAR-зависимости возникают, когда операция сохранения записывает в память значение, которое считывает предыдущая загрузка.
  • Запись после записи (WAW) зависимости: также известные как выходные зависимости, зависимости WAW возникают, когда две операции сохранения записывают значения в один и тот же адрес памяти.

Три зависимости показаны в предыдущем сегменте кода (воспроизведены для ясности):

1: div 27 долларов, 202 доллара: 27 долларов США, 0 (30 долларов) 3: lw 08 долларов США, 0 (31 доллар США) 4: 26 долларов США, 0 (30 долларов США) 5: lw 09 долларов США, 0 (31 доллар США)
  • В lw $ 08, 0 (31 $) инструкция в строке 3 имеет RAW-зависимость от 27 евро, 0 (30 долларов) инструкция в строке 2, а lw $ 09, 0 (31 $) инструкция в строке 5 имеет RAW-зависимость от 26,00 швейцарских долларов (30 долларов) инструкция в строке 4. Обе инструкции загрузки читают адрес памяти, записанный предыдущими хранилищами. Хранилища были самыми последними производителями для этого адреса памяти, и нагрузки считывают значение этого адреса памяти.
  • В 26,00 швейцарских долларов (30 долларов) инструкция в строке 4 имеет зависимость WAR от lw $ 08, 0 (31 $) в строке 3, так как она записывает адрес памяти, из которого считывается предыдущая загрузка.
  • В 26,00 швейцарских долларов (30 долларов) инструкция в строке 4 имеет зависимость WAW от 27 евро, 0 (30 долларов) инструкция в строке 2, поскольку оба хранилища записывают по одному и тому же адресу памяти.

Механизмы устранения неоднозначности в памяти

Современные микропроцессоры используют следующие механизмы, реализованные в аппаратное обеспечение, чтобы разрешить неоднозначные зависимости и восстановить при нарушении зависимости.

Избегание зависимостей WAR и WAW

Значения из инструкций хранилища не передаются в систему памяти (в современных микропроцессорах Кэш процессора ), когда они выполняются. Вместо этого инструкции сохранения, включая адрес памяти и данные сохранения, буферизируются в хранить очередь пока они не достигнут пенсионного возраста. Когда магазин закрывается, он тогда записывает свое значение в систему памяти. Это позволяет избежать проблем зависимости WAR и WAW, показанных в приведенном выше фрагменте кода, когда более ранняя загрузка получает неверное значение из системы памяти, потому что более позднему хранилищу было разрешено выполняться до более ранней загрузки.

Кроме того, буферизация хранилищ до вывода из эксплуатации позволяет процессорам спекулятивно выполнять инструкции хранилища, которые следуют инструкциям, которые могут производить исключение (например, загрузка неверного адреса, деление на ноль и т. д.) или условная ветвь инструкция, направление которой (принято или не принято) пока не известно. Если вызывающая исключение инструкция не была выполнена или направление ветвления было предсказано неверно, процессор будет выбирать и выполнять инструкции по «неправильному пути». Эти инструкции вообще не должны были выполняться; условие исключения должно было произойти до того, как была выполнена какая-либо из предполагаемых инструкций, или ветвь должна была пойти в другом направлении и вызвать выборку и выполнение различных инструкций. Процессор должен «отбросить» любые результаты неверного пути, предположительно выполненных инструкций, когда он обнаруживает исключение или неверное предсказание перехода. Сложность для хранилищ заключается в том, что любые хранилища на неверном или неверно предсказанном пути не должны передавать свои значения в систему памяти; если бы хранилища зафиксировали свои значения, было бы невозможно "выбросить" фиксацию, и состояние памяти машины было бы искажено данными из инструкции сохранения, которая не должна была выполняться.

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

Сохранить для пересылки груза

Буферизация хранилищ до выхода на пенсию позволяет избежать зависимостей WAW и WAR, но создает новую проблему. Рассмотрим следующий сценарий: магазин выполняет и буферизует свой адрес и данные в очереди магазина. Через несколько инструкций выполняется загрузка, которая читает из того же адреса памяти, по которому только что записано хранилище. Если загрузка считывает свои данные из системы памяти, она считывает старое значение, которое было бы перезаписано предыдущим хранилищем. Данные, полученные при загрузке, будут неверными.

Для решения этой проблемы в процессорах используется метод, называемый пересылка от магазина к загрузке используя очередь магазина. В дополнение к буферизации хранилищ до вывода из эксплуатации, очередь хранилищ служит второй цели: пересылка данных из завершенных, но еще не выведенных из эксплуатации («находящихся в эксплуатации») хранилищ для последующих загрузок. Вместо простого ФИФО очередь, очередь магазина действительно Память с адресацией по содержимому (CAM) поиск по адресу памяти. Когда выполняется загрузка, она ищет в очереди хранилища оперативные хранилища по тому же адресу, который логически расположен раньше в программном порядке. Если соответствующее хранилище существует, загрузка получает значение данных из этого хранилища, а не из системы памяти. Если подходящего хранилища нет, загрузка обращается к системе памяти как обычно; любые предшествующие подходящие магазины должны быть уже выведены из эксплуатации и зафиксированы в своих значениях. Этот метод позволяет загрузкам получать правильные данные, если их хранилище производителя завершено, но еще не закрыто.

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

Нарушения RAW-зависимости

Выявление нарушений RAW-зависимости

Современные ЦП, вышедшие из строя, могут использовать ряд методов для обнаружения нарушения зависимости RAW, но все методы требуют отслеживания нагрузки в полете от выполнения до вывода из эксплуатации. Когда загрузка выполняется, она обращается к системе памяти и / или очереди хранилища, чтобы получить значение своих данных, а затем ее адрес и данные буферизируются в очередь загрузки до пенсии. Очередь загрузки аналогична по структуре и функциям очереди в хранилище, и фактически в некоторых процессорах она может быть объединена с очередью в хранилище в единую структуру, называемую очередь загрузки-магазина, или же LSQ. Для выявления нарушений RAW-зависимости используются или были предложены следующие методы:

Загрузка очереди поиска CAM

При использовании этого метода очередь загрузки, как и очередь хранилища, представляет собой CAM, поиск которого выполняется с использованием адреса доступа к памяти, и отслеживает все нагрузки в полете. Когда хранилище выполняется, оно ищет в очереди загрузки завершенные загрузки с того же адреса, которые логически находятся позже в программном порядке. Если такая подходящая нагрузка существует, она должна быть выполнена до сохранения и, таким образом, считывать неправильное старое значение из системы памяти / очереди хранилища. Любые инструкции, которые использовали значение нагрузки, также использовали неверные данные. Для восстановления, если такое нарушение обнаружено, нагрузка помечается как «нарушенная» в буфере вывода из эксплуатации. Хранилище остается в очереди хранилища и в буфере вывода из эксплуатации и обычно закрывается, передавая свое значение системе памяти при закрытии. Однако, когда нарушенная нагрузка достигает точки списания, процессор очищает конвейер и перезапускает выполнение с инструкции загрузки. На этом этапе все предыдущие хранилища передали свои значения в систему памяти. Команда загрузки теперь будет считывать правильное значение из системы памяти, и все зависимые инструкции будут повторно выполняться с использованием правильного значения.

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

Устранение неоднозначности на пенсии

С помощью этого метода инструкции загрузки, которые были выполнены не по порядку, повторно выполняются (они обращаются к системе памяти и читают значение со своего адреса во второй раз), когда они достигают точки выхода из эксплуатации. Поскольку загрузка теперь является инструкцией по удалению, она не зависит от какой-либо инструкции, все еще находящейся в работе; все предшествующие хранилища передали свои значения в систему памяти, поэтому любое значение, считываемое из системы памяти, гарантированно будет правильным. Значение, считанное из памяти во время повторного выполнения, сравнивается со значением, полученным при первом выполнении загрузки. Если значения совпадают, исходное значение было правильным и никаких нарушений не произошло. Если значение повторного выполнения отличается от исходного значения, произошло нарушение RAW, и конвейер необходимо очистить, потому что инструкции, зависящие от загрузки, использовали неправильное значение.

Этот метод концептуально проще, чем поиск в очереди загрузки, и он устраняет второй CAM и его энергоемкий поиск (теперь очередь загрузки может быть простой очередью FIFO). Поскольку загрузка должна повторно обращаться к системе памяти непосредственно перед выводом из эксплуатации, доступ должен быть очень быстрым, поэтому эта схема полагается на быстрый кэш. Однако независимо от того, насколько быстрым является кеш, второй доступ к системе памяти для каждой неупорядоченной инструкции загрузки увеличивает удаление инструкций. задержка и увеличивает общее количество обращений к кэш-памяти, которые должны быть выполнены процессором. Дополнительный доступ к кэш-памяти при удалении может быть удовлетворен путем повторного использования существующего порта кэш-памяти; однако это создает конкуренцию за ресурсы порта с другими загрузками и хранилищами в процессоре, которые пытаются выполнить, и, таким образом, может вызвать снижение производительности. В качестве альтернативы можно добавить дополнительный порт кеша только для устранения неоднозначности нагрузки, но это увеличивает сложность, мощность и площадь кеша. Некоторые недавние работы (Roth 2005) показали способы отфильтровать множество загрузок от повторного выполнения, если известно, что не могло произойти никакого нарушения зависимости RAW; такой метод помог бы или устранил такую ​​задержку и конкуренцию за ресурсы.

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

Как избежать нарушений RAW-зависимости

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

Первый вариант, при котором загрузка и сохранение идет по порядку, позволяет избежать зависимостей от RAW, поскольку нет возможности выполнения загрузки до сохранения ее производителем и получения неверных данных. Другая возможность - эффективно разбить загрузку и сохранение на две операции: создание адреса и доступ к кешу. С помощью этих двух отдельных, но связанных операций ЦП может разрешить загрузкам и хранилищам доступ к системе памяти только после того, как все предыдущие загрузки и хранилища сгенерировали свои адреса и занесли их в буфер в LSQ. После генерации адреса больше нет неоднозначных зависимостей, так как все адреса известны, и поэтому зависимые загрузки не будут выполняться до тех пор, пока не будут завершены их соответствующие хранилища. Эта схема по-прежнему допускает некоторую "неупорядоченность" - операции генерации адресов для любых загрузок и хранилищ в полете могут выполняться не по порядку, и после создания адресов доступ к кешу для каждой загрузки или хранилища может происходят в любом порядке, который соблюдает (теперь известные) истинные зависимости.

Дополнительные вопросы

Прогнозирование зависимости от памяти

Процессоры, которые полностью поддерживают выполнение загрузки / сохранения вне очереди, могут использовать дополнительную связанную технику, называемую прогноз зависимости от памяти, чтобы попытаться предсказать истинные зависимости между загрузками и магазинами перед их адреса известны. Используя этот метод, процессор может предотвратить выполнение нагрузок, которые, согласно прогнозам, зависят от оперативного хранилища, до завершения этого хранилища, избегая нарушения зависимости RAW и, таким образом, избегая очистки конвейера и возникающего снижения производительности. См. Статью о прогнозировании зависимости от памяти для получения более подробной информации.

Смотрите также