3

Согласно статье Real World Technologies о микроархитектуре Intel Sandy Bridge :

«Кэш-память мопов Sandy Bridge организована в 32 набора и 8 способов, по 6 моп на линию, что в общей сложности составляет 1,5 тыс. Мопов. Кэш UOP строго включен в кэш команд L1. Каждая строка также содержит метаданные, включая число допустимых значений uops в строке и длину инструкций x86, соответствующих строке кэша uop. Каждое окно 32B, отображаемое в кэш-память UOP, может охватывать 3 из 8 способов в наборе, максимум 18 моп - примерно 1,8 Б / моп. Если окно 32B имеет более 18 мопов, оно не может поместиться в кеш мопов и должно использовать традиционный внешний интерфейс. Микрокодированные инструкции не хранятся в кэше UOP, а вместо этого представлены указателем на ПЗУ микрокода и, возможно, первыми несколькими мопами ».

«Каждое окно 32B (из кэша команд) отображается в кэш UOP, может охватывать 3 из 8 способов набора»

Итак, предположим, что у нас есть окно команд 32B, которое будет половиной строки кэша команд L1, в этой строке будут отличаться только биты смещения, но биты тега и набора будут одинаковыми для всех байтов в строке.

После того как 32-байтовое окно было декодировано, мопы вводятся в кеш мопов с тем же виртуальным адресом, который использовался для извлечения 16-байтового блока выборки из кеша инструкций L1 (чтобы их можно было проверять параллельно на каждом поле 32B)

Это говорит о том, что эти мопы могут охватывать 3 из 8 способов в наборе, но это будет означать, что они должны будут иметь одинаковые биты набора, но разные биты тега, чтобы оказаться в одном наборе (то есть они не были бы включены та же самая строка в кеше L1I), означает ли это, что кэш мопов расположен немного по-другому, один виртуальный адрес в начале строки, и мопы просто заполняются следующим способом в наборе и следующим способом в задавать. Как гарантируется, что следующее окно инструкций 32B, которое все еще будет иметь тот же тег и те же самые биты, но разные биты смещения (2-я половина строки 64 B в L1I), сопоставлено с 4-м способом этого набора.

Постулат: путь кэш-памяти uop помечается физическим тегом виртуального индекса, следующий путь - ничем, третий - ничем, четвертый - виртуальным индексом / физическим тегом, где разница в том, что смещение изменилось с 0 на 32, так что, по сути, способ может быть выбран с использованием разных битов смещения, в отличие от способа пометки кеша L1I: биты смещения функционируют как смещение для строки кеша.

Кто-нибудь может уточнить расположение кэшей UOP или как на самом деле работает эта маркировка?

1 ответ1

1

Обратите внимание, что AMD Zen также имеет кэш UOP, но о его внутренних компонентах известно меньше. Так что вы спрашиваете конкретно о UOP-кэше Intel в семействе Sandybridge.

Согласно тестированию Агнера Фога (https://www.agner.org/optimize/, в частности, его микроархив pdf), он практически адресован (VIVT), сохраняя время ожидания / мощность поисков iTLB для попаданий в uop-кэш. И, тем не менее, позволяя по-прежнему очень тесно интегрировать iTLB с кешем L1i, как обычно для кеша VIPT L1.

(также связано: какая технология отображения кэша используется в процессоре Intel Core i7? краткий обзор этого и других кэшей и https://stackoverflow.com/tags/x86/info для получения дополнительных ссылок на производительность / uarch.)

После того, как 32-байтовое окно было декодировано

Вот где вы ошиблись в своем мыслительном процессе.

Кэш мопов кэширует только те мопы, которые декодируются по пути (спекулятивного) выполнения. Инструкции x86 могут быть правильно декодированы, только если вы знаете правильную начальную точку. Байты после безусловного jmp могут вообще не быть началом инструкции.

Кроме того, вы не хотите загрязнять кэш UOP множеством однобайтовых инструкций заполнения между функциями (например, 0x90 NOP или 0xcc int3 используемые MSVC). Или вообще, с "холодными" инструкциями, которые не достигаются во время обычного выполнения после выбранной ветви. "Строка" / путь uop-кэша рано заканчивается безусловным переходом или call .

Устаревшие декодеры являются либо инструкциями декодирования, которые ЦП ожидает фактически выполнить (направляя их в кэш-память uop для повторного использования позже, а IDQ напрямую для использования сразу), либо они отключаются. В отличие от P4, старые декодеры не являются слабыми; они похожи на декодеры в Core2 / Nehalem, поэтому выполнение из L1i в целом нормально, за исключением высокопроизводительного кода с большим средним размером команд. Им не нужно пытаться "строить следы" заранее. (Кэш uop в любом случае не является кэшем трассировки; он не следует за переходами. Но в любом случае он не пытается заполнить кэш uop для всех 32 байтов инструкций, которые могут быть кешированы сразу.)

Но что интересно, Агнер говорит: « Один и тот же фрагмент кода может иметь несколько записей в кэше μop, если в нем несколько записей перехода ».


Мое лучшее предположение о том, как на самом деле работает механизм поиска в кэше:

Имеется 64-битный виртуальный адрес для извлечения кода из:

  • Младшие 5 битов являются смещением относительно 32-байтовой границы.
  • Следующие 5 битов являются индексом. Не 6 бит для 64-байтовых линий L1i; выборка из кэша UOP напрямую не заботится об этом.
  • Старшие биты (до бита 48) являются тегом.

Используйте 5-битный индекс для выбора набора.
Получить все 8 способов из этого набора (тег + метаданные, а также данные параллельно, потому что это высокопроизводительный кеш).

Сравните параллельно для всех 8 способов:

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

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

Это догадки, основанные на том, как работает кэш uop и когда он выбрасывает пути. Но это может помочь вам получить полезную мысленную модель этого.


Обратите внимание, что адрес не должен быть выровнен по 16 байтов. Он должен эффективно поддерживать целевые объекты ветвления, которые не выровнены, а также прямой код с границами команд, которые не совпадают с 32-байтовыми границами. (Насколько я могу судить, инструкции, которые пересекают 32-байтовую границу, кэшируются способом uop-cache для начального адреса команды, даже если она заканчивается в следующей строке кэша L1i через 64-байтовую границу.)

Блоки извлечения / предварительного декодирования L1i для длины команды выровнены, но полное декодирование в унаследованных декодерах работает с до 16 байтов любого выравнивания, взятого из очереди между предварительным декодированием и декодированием. Выравнивание точек входа в цикл по определенным границам выравнивания менее важно, чем раньше.


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

Кэш-память uop не может одновременно кэшировать оба пути, поэтому при обнаружении этого ЦПУ должен обратиться к устаревшим декодерам и выбросить пути кэша uop для этого блока 32B (который он уже обнаружил с помощью компаратора тегов).

Затем он может начать повторное заполнение кеша uop, поскольку он декодирует мопы с этой точки.

Аналогичная ситуация происходит, когда 3 пути уже заполнены, но в одном и том же блоке 32B машинного кода x86 имеется больше мопов. Uop-кеш выбрасывает все 3 пути для этого блока. (Я не уверен, что он помнит, чтобы не пытаться кэшировать их в следующий раз, или он просто каждый раз создает кеш и выбрасывает его, когда достигает предела, например, в цикле с 20 однобайтовыми инструкциями nop .)

Посмотрите выравнивание Ветви для циклов, вовлекающих микрокодированные инструкции на процессорах семейства Intel SnB для некоторых деталей об этом случае. Обратите внимание, что микрокодированные инструкции, такие как div самостоятельно используют весь путь кеша uop и могут легко привести к заполнению всех трех способов и запуску переключателей DSB-to-MITE (переключатели uop-кеш к устаревшим декодерам могут создать 1 цикл пузыря в передней части).

Этот Q & A имеет много подробных экспериментов и выводов о том, как кэшируются мопы. Не так много о том, как физически реализован кэш UOP; это просто догадки с моей стороны здесь.

Также обратите внимание, что процессоры Intel до Skylake могут добавлять только 4 мопа в IDQ из кеша мопов, но почему-то не ставят узкое место, когда в кеше мопов есть пути, которые имеют 3 или 6 моп вместо 4. Так что IDK, если есть какая-то буферизация для не разветвляющейся выборки uop. Это немного загадка. Можно ожидать, что fetch будет идти по схеме 4, 2, 4, 2, если выборка выполняется из полных строк по 6 моп каждый, но мы не видим такого узкого места во внешнем интерфейсе, как для циклов, запущенных из кеша uop с 2 -байтовые инструкции, такие как xor eax,eax . Корпорация Intel заявила, что кэш-память uop может извлекать мопы только по одному пути за цикл, поэтому, возможно, ограничение в 4 моп просто для добавления в IDQ, а не для чтения из кеша uop в некоторый буфер слияния.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .