VIPT Cache: соединение между TLB и кешем?

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

В случае кэшей VIPT запрос памяти отправляется параллельно как TLB, так и кешу.

Из TLB мы получаем переведенный физический адрес. Из индексации кеша мы получаем список тегов (например, из всех строк кеша, принадлежащих набору).

Затем переведенный адрес TLB сопоставляется со списком тегов для поиска кандидата.

  • My question is where is this check performed ?
    • In Cache ?
    • Если не в кэше, то где еще?
  • If the check is performed in Cache, then
    • is there a side-band connection from TLB to the Cache module to get the translated physical address needed for comparison with the tag addresses?

Может кто-нибудь пролить свет на «на самом деле», как это обычно реализовано, и на связь между модулем кеширования и модулем TLB (MMU)?

Я знаю, что это зависит от конкретной архитектуры и реализации. Но какова реализация, которую вы знаете, когда есть кеш VIPT?

Спасибо.


person Uchia Itachi    schedule 29.09.2017    source источник


Ответы (1)


На этом уровне детализации необходимо разбить кеш и TLB на составные части. Они очень тесно связаны между собой в дизайне, в котором используется скоростной прием VIPT для перевода параллельно с выборкой тегов (т. Е. С использованием всех битов индекса, которые находятся ниже смещения страницы и, следовательно, переводятся бесплатно. Связано: Почему размер кэша L1 меньше, чем размер кэша L2 в большинстве процессоров?)

Сам L1dTLB представляет собой небольшую / быструю память с адресацией по содержимому с (например) 64 записями. и 4-сторонний ассоциативный набор (Intel Skylake). Огромные страницы часто обрабатываются с помощью второго (и третьего) массива, проверяемого параллельно, например 32 записи, 4 страницы для 2M страниц, и для страниц 1G: полностью ассоциативная (4-сторонняя) с 4 записями.

Но пока упростите свою ментальную модель и забудьте об огромных страницах. L1dTLB - это одиночный CAM, и его проверка - это единственная операция поиска.

Кэш состоит как минимум из следующих частей:

  • массив SRAM, в котором хранятся теги + данные в наборах
  • логика управления для выборки набора данных + тегов на основе битов индекса. (Высокопроизводительные кэши L1d обычно извлекают данные для всех способов набора параллельно с тегами, чтобы уменьшить задержку обращения по сравнению с ожиданием выбора правильного тега, как если бы вы использовали более крупные и высокоассоциативные кеши.)
  • компараторы для проверки тегов на соответствие переведенному адресу и выбора правильных данных, если один из них совпадает, или запуска обработки ошибок. (И при ударе обновите биты LRU, чтобы пометить этот способ как наиболее недавно использованный). Основную схему двухстороннего ассоциативного кэша без TLB см. В https://courses.cs.washington.edu/courses/cse378/09wi/lectures/lec16.pdf#page=17.. = внутри круга - это компаратор: выдача логического истинного вывода, если входные значения ширины тега равны.

L1dTLB на самом деле не отделен от кеша L1D. На самом деле я не занимаюсь разработкой оборудования, но считаю, что модуль выполнения загрузки в современном высокопроизводительном дизайне работает примерно так:

  • AGU генерирует адрес из регистра (ов) + смещение.

(Интересный факт: семейство Sandybridge оптимистично сокращает этот процесс для простого режима адресации: [reg + 0-2047] имеет на 1с меньшую задержку использования нагрузки, чем другие режимы адресации, если значение reg находится на той же странице 4k, что и reg+disp. Есть ли штраф, если база + смещение находится в другом страница, чем база?)

  • Биты индекса берутся из части адреса со смещением внутри страницы, поэтому их не нужно переводить из виртуального в физический. Или перевод не работает. Эта скорость VIPT с отсутствием алиасинга кэша PIPT работает до тех пор, пока L1_size / associativity <= page_size. например 32kB / 8-полосный = 4k страниц.

    Биты индекса выбирают набор. Теги + данные извлекаются параллельно для всех способов этого набора. (Это стоит энергии для экономии времени ожидания и, вероятно, того стоит только для L1. Более высокая ассоциативность (больше способов на набор) L3 кешей определенно нет)

  • Старшие биты адреса ищутся в массиве L1dTLB CAM.

  • Компаратор тегов получает переведенный тег физического адреса и выбранные теги из этого набора.

  • Если есть совпадение тега, кеш извлекает из данных правильные байты таким образом, чтобы они совпадали (используя младшие биты смещения внутри строки адреса и размер операнда).

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

Но современные процессоры Intel (P6 и новее) не имеют штрафа за невыровненные операторы загрузки даже для 32-байтовых векторов, если они не пересекают границу строки кэша. Индексация с байтовой детализацией для 8 параллельных способов, вероятно, стоит больше, чем просто выборка всех 8 x 64 байтов и настройка мультиплексирования вывода во время выполнения выборки + TLB на основе смещения внутри строки, размера операнда и специальные атрибуты, такие как нулевое или знаковое расширение, или широковещательная загрузка. Таким образом, как только сравнение тегов будет выполнено, 64 байта данных из выбранного способа могут просто перейти в уже настроенную мультиплексную сеть, которая захватывает нужные байты и передает или расширяет знак.

Процессоры AVX512 могут даже выполнять 64-байтную загрузку полной строки.


Если в L1dTLB CAM нет совпадений, вся операция выборки из кеша не может продолжаться. Я не уверен, удастся ли / как процессорам передать это, чтобы другие нагрузки могли продолжать выполняться, пока устранена ошибка TLB. Этот процесс включает проверку L2TLB (Skylake: унифицированная запись 1536, 12 каналов для 4 КБ и 2 МБ, 16 записей для 1 ГБ), а если это не удается, то с обходом страниц.

Я предполагаю, что промах TLB приводит к тому, что тег + выборка данных отбрасываются. Они будут повторно загружены, как только будет найден нужный перевод. Их негде держать, пока работают другие нагрузки.

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

Очевидно, для этого требуется, чтобы dTLB и L1D действительно были спроектированы вместе и тесно интегрированы. Поскольку им нужно только поговорить друг с другом, это имеет смысл. Страница оборудования выполняет выборку данных через кеш L1D. (Таблицы страниц всегда имеют известные физические адреса, чтобы избежать проблемы «уловка 22 / курица-яйцо»).

есть ли боковая связь между TLB и кешем?

Я бы не назвал это подключением по боковой полосе. Кэш L1D - это единственное, что использует L1dTLB. Точно так же L1iTLB используется только кешем L1I.

Если есть TLB 2-го уровня, он обычно унифицирован, поэтому и L1iTLB, и L1dTLB проверяют его, если они отсутствуют. Точно так же, как разделенные кеши L1I и L1D обычно проверяют унифицированный кеш L2, если они отсутствуют.

Внешние кеши (L2, L3) почти всегда являются PIPT. Трансляция происходит во время проверки L1, поэтому физические адреса могут быть отправлены в другие кеши.

person Peter Cordes    schedule 29.09.2017
comment
предостережение: я не настоящий архитектор ЦП, поэтому мое понимание может быть ошибочным. Некоторые детали моих примеров могут быть неточными. Но см. realworldtech.com/haswell-cpu/5 и обратите внимание, что L1dTLB блок прикреплен к блоку L1D, не связан стрелкой, как блок AGU - ›L1D. Дэвид Кантер - аналитик микроархитектуры ЦП (и его статьи о SnB, HSW и Bulldozer превосходны), так что это подтверждает то, что я говорю в этом ответе. - person Peter Cordes; 29.09.2017
comment
Поддержку невыровненных нагрузок можно осуществить двумя способами: (1) использовать несколько выровненных нагрузок, (2) спроектировать более сложную схему для обработки невыровненных нагрузок с высокой производительностью, но за счет дополнительного оборудования и накладных расходов на электроэнергию. Допустим, мы хотим разработать схему для поддержки выровненных 32-байтовых, 16-байтовых, 8-байтовых и 4-байтовых загрузок из 64-байтовых строк кэша. Один из возможных вариантов состоит в использовании 64 простых вентилей включения / выключения для каждого из 64 байтов. Сигнал разрешения для каждого затвора вычисляется с использованием простой логической комбинации верхних 4 бит 6-битного смещения строки ... - person Hadi Brais; 20.02.2019
comment
... Например, чтобы получить первые 16 байтов, сигнал разрешения будет вычисляться как 5-й бит И 4-й бит. Два других бита маскируются в один с использованием маски размера нагрузки, так что разрешающий сигнал включается для указанных ворот. Если мы хотим получить нижние 16 байтов, сигнал разрешения НЕ (5-й) И НЕ (4-й) и так далее. Для эффективной поддержки невыровненных нагрузок расчет разрешающих сигналов усложняется. Для поддержки 2-байтовых и 1-байтовых нагрузок в один из возможных вариантов можно добавить еще один уровень шлюзов (что может привести к задержке +1 цикла) ... - person Hadi Brais; 20.02.2019
comment
... Те вентили, которые включены, выводят загруженные биты, а те вентили, которые отключены, выводят нули. Затем все биты сдвигаются по мере необходимости, и наиболее значимый бит объединяется оператором ИЛИ со всеми старшими битами для реализации нулевого и знакового расширения. Наконец, результат записывается в указанный регистр. Возможны и другие конструкции, но поддержка ненагруженных нагрузок аппаратными средствами всегда сложнее. - person Hadi Brais; 20.02.2019
comment
В современных процессорах все TLB и обходчик страниц имеют MSHR, аналогичные L1D. Если запрос пропущен в TLB, он прерывается, и все загрузки, для которых требуется эта запись в таблице страниц, блокируются в буфере загрузки. Позже, когда TLB заполняется, нагрузки пробуждаются и воспроизводятся из буфера загрузки. - person Hadi Brais; 20.02.2019
comment
@HadiBrais: Описание в моем ответе - это попытка объяснить поведение семейства P6 / SnB, в котором невыровненные мопы нагрузки имеют точно такую ​​же задержку, как и выровненные. (До Nehalem movups 16-байтовые нагрузки декодировались в большее количество мопов. Core2 и P4 - единственные архивы с одинарными 16-байтовыми выровненными нагрузками; более раннее семейство P6 делилось на 8-байтовые половины. Но невыровненные 8-байтовые нагрузки, которые не выполнялись Не разделенные строки кэша по-прежнему являются атомарными. И я думаю, что нет штрафа за задержку. Определенно нет штрафа за задержку для невыровненных нагрузок в семействе SnB.) - person Peter Cordes; 21.02.2019
comment
@HadiBrais: В любом случае, как вы думаете, вероятно ли, что кеши Intel L1d выполняют необходимое декодирование для включения / отключения байтов для параллельной выборки данных всеми 8 способами, вместо того, чтобы делать это декодирование только для одного способа, выбранного компараторами тегов? До SKX / AVX512, который заставлял бы тэг-компаратор мультиплексировать не более 32 байтов, но с SKX 64-байтовые невыровненные нагрузки - это вещь, поэтому любое количество байтов от 1 до 64 могло потребоваться из строки для (части ) нагрузка. Однако дизайн мог измениться в любой момент по мере расширения векторов. - person Peter Cordes; 21.02.2019
comment
Верно. Я только описывал, насколько сложнее поддерживать невыровненные нагрузки в целом, а не то, как они реализованы в каком-либо конкретном процессоре. Обратите внимание, что вопрос не относится к какому-либо процессору. - person Hadi Brais; 21.02.2019
comment
Точно не знаю. Я думаю, что логика выбора байта и сдвига происходит после сравнения тегов. 64-байтовая невыровненная нагрузка пересекает не более одной строки. Декодирует ли SKX 64-байтовую невыровненную загрузку в 2 мопа загрузки? Это наложило бы штраф за производительность, требуя либо двух портов загрузки, либо использования логики слияния. Если мы хотим избежать потери производительности, нам нужно иметь возможность выбирать и обрабатывать две строки из одного порта. Для этого потребуется много дополнительного оборудования. - person Hadi Brais; 21.02.2019
comment
@HadiBrais: нет, vmovups zmm или dqu32, по словам Агнера Фога, по-прежнему является одним муп, без штрафа, если данные выровнены во время выполнения. Я предполагаю, что это просто расширяет регистры с разделенной загрузкой. (В описании счетчика производительности для ld_blocks.no_sr он описан как заблокированный, поскольку все ресурсы для обработки разделенного доступа используются. software.intel.com/en-us/vtune-amplifier-help-split-loads использует термин разделенные регистры.) Я предполагаю, что загрузка затем работает как 2 невыровненных загрузки произвольной ширины от 2-х линий, которых он касается, сливаясь в разделенный регистр. - person Peter Cordes; 21.02.2019
comment
uops.info показывает, что IACA моделирует VMOVUPS (ZMM, K, M512) как 2 мупа, в отличие от таблицы Агнера. Также таблица Агнера показывает более высокую задержку для инструкции. В целом мне неясно, действительно ли эти числа представляют собой невыровненный случай. - person Hadi Brais; 21.02.2019
comment
@HadiBrais: Я смотрел на немаскированные грузы. Очевидно, что p05 ALU uop предназначен для маскировки. Обратите внимание, что в таблице Агнера Фога есть 2 строки: одна без маскирования (чистая нагрузка для vmovdq[au]8/16/32/64 v,m) и одна с маскировкой (1 микроплавкий ALU + нагрузочный верхний порог для vmovdqu[au]8/16/32/64 v{k},m). В любом случае, даже в выводе IACA вы можете видеть, что дополнительный uop - это p05, а не p23, так что это не загрузка uop. - person Peter Cordes; 21.02.2019
comment
В разделе B.5.4.4 руководства по оптимизации упоминаются регистры разделения (они существуют со времен Nehalem для обработки загрузки и сохранения разделенных строк). Там написано, что они находятся в L1D. Обратите внимание, что две последовательные строки (на одной странице 4K) отображаются в два последовательных набора и, возможно, разными способами. Таким образом, либо необходимо использовать два порта нагрузки, либо один порт будет занят на дополнительный цикл. Я думаю, что регистр разделения используется для буферизации двух строк, пока они извлекаются из их соответствующих наборов, а затем он извлекает необходимые байты. - person Hadi Brais; 21.02.2019
comment
О, похоже, uops.info показал мне только маску, а таблица Агнера показывает только немаскировку, и я подумал, что они такие же. Но все же, если я понимаю цифры Агнера, я думаю, что задержка выше, чем обычно. - person Hadi Brais; 21.02.2019
comment
@HadiBrais: нет, таблицы Агнера показывают оба. У вас последняя версия? В таблице SKX есть 2 последовательные строки для yz, m и v{k}, m. - person Peter Cordes; 21.02.2019
comment
@HadiBrais: да, это похоже на то, что я представлял себе сплит-регов. Я только что проверил, и мопы с разделенной загрузкой действительно воспроизводятся. uops_dispatched_port.port_2 + port_3 = 2x количество mov rdi, [rdi] выполненных инструкций. Но подсчеты для uops_issued.any (выдача / переименование объединенного домена) и uops_executed.thread (незафиксированный домен) подсчитывают нагрузку только один раз. - person Peter Cordes; 21.02.2019
comment
Невозможно, чтобы uop загрузки был разделен в RS, чтобы занимать два RS и две записи буфера загрузки? В любом случае, я думаю, это снизило бы пропускную способность вдвое, а то и увеличило бы задержку. - person Hadi Brais; 21.02.2019
comment
@HadiBrais: Вы не можете обнаружить разделенную нагрузку до тех пор, пока не закончится AGU, для чего требуется, чтобы входы регистров были готовы (если только это не режим абсолютной или относительной адресации RIP). Выделение 2-го места в RS после однократной отправки нагрузки и обнаружения ее разделения не имеет смысла, поэтому я не думаю, что это правдоподобно. Мы уже знаем, что разделенные нагрузки имеют половину пропускной способности и большую задержку. Как я могу точно измерить скорость невыровненного доступа на x86_64. Надеюсь, если первая строка отсутствует в кеше, вторая строка все еще может начать выборку до того, как она появится? - person Peter Cordes; 21.02.2019
comment
Я думаю, что всегда есть штраф при пересечении строки кеша даже для 64-байтовых нагрузок на SKX. Как я уже сказал в своем первом комментарии, есть два способа поддержки невыровненных способов, и ваш тест на пересечение линии mov rdi, [rdi] подтверждает, что два выровненных запроса нагрузки (считающихся двумя неиспользуемыми мопами домена) используются для реализации невыровненной нагрузки, а разделенный регистр - выделяется после AGU для обработки слияния. Остается два открытых вопроса: сколько всего разделенных регистров и может ли быть выполнена вторая согласованная загрузка, даже если первая пропущена? Я думаю, что pf следующей строки L1 будет здесь очень полезен. - person Hadi Brais; 21.02.2019
comment
@HadiBrais: Да, конечно, любое разделение строки кэша имеет штраф. Я говорил о каждой стороне 64-байтовой невыровненной нагрузки отдельно. (И в какой-то момент речь идет о 64-байтовых выровненных загрузках, просто чтобы указать, что SKX, по крайней мере, иногда нужно извлекать данные для всей строки.) О, хм, мне интересно, могут ли широкие векторные загрузки использовать другой механизм, который не использует ' t получать данные параллельно с тегами? Это может объяснить более высокую задержку на 1 цикл для 256-битных векторных загрузок по сравнению со 128-битными или скалярными в SKL. (Но это переадресация магазина, а не доступ к L1d agner.org/optimize /blog/read.php?i=415#854) - person Peter Cordes; 21.02.2019
comment
@HadiBrais: re: могут ли обе половины разделения иметь невыполненные запросы на пропуск: я подумал об этом еще немного, редактируя обновление на Как я могу точно оценить невыровненный доступ скорость на x86_64. Если я правильно понимаю, ошибка загрузки кеша не должна сама воспроизводиться, а просто зависит от ошибки. Таким образом, не должно быть препятствий для того, чтобы разделенная загрузка запрашивала повторное воспроизведение для загрузки другой стороны разделения, независимо от того, попала ли она в L1d или нет. Виртуальный адрес для загрузки не зависит от данных загрузки. Так что я не вижу препятствий для этого. - person Peter Cordes; 21.02.2019