Интересный вопрос, как только вы преодолеете некоторые заблуждения (см. Мои комментарии к вопросу).
Выборка / декодирование происходит строго в программном порядке. Нет механизма для декодирования блока из более поздней строки кэша в ожидании пропуска L1i, даже для заполнения uop-кэша. Насколько я понимаю, кэш-память uop всегда заполняется только инструкциями, которые ЦП ожидает выполнить на текущем пути выполнения.
(инструкции переменной длины x86 означают, что вам нужно знать границу команд, прежде чем вы сможете даже начать декодирование. Это может быть возможно, если прогнозирование ветвлений говорит, что блок инструкций пропущенного кеша разветвляется где-то в другой строке кеша, но текущий аппаратное обеспечение не построено таким образом. Некуда помещать декодированные инструкции, в которых процессор мог бы вернуться и заполнить пробел.)
Есть аппаратная предварительная выборка в L1i (которая, как я полагаю, использует предсказание ветвления, чтобы знать, куда переходить дальше, даже если текущая выборка заблокирована при пропадании кэша), поэтому выборка кода может генерировать несколько ожидающих нагрузок параллельно, чтобы сохранить конвейер памяти лучше занят.
Но да, промах L1i создает пузырь в конвейере, который длится до тех пор, пока данные не поступят из L2. Каждое ядро имеет собственный частный L2 для каждого ядра, который заботится о том, чтобы отправлять запросы вне ядра, если он пропускает L2. WikiChip показывает , путь данных между L2 и L1i имеет ширину 64 байта в Skylake-SP.
https://www.realworldtech.com/haswell-cpu/6/ показывает, что L2 <-> L1d имеет ширину 64 байта в Haswell и более поздних версиях, но не показывает столько деталей для выборки инструкций. (Что часто не является узким местом, особенно для циклов малого и среднего размера, которые попадают в кэш UOP.)
Есть очереди между извлечением, предварительным декодированием (границами команд) и полным декодированием, которые могут скрывать / поглощать эти пузырьки и иногда мешать им достигать декодеров и фактически снижать пропускную способность декодирования. И есть большая очередь (64 мопа на Skylake), которая передает этап выпуска / переименования, называемый IDQ. Инструкции добавляются в IDQ из кэша UOP или из устаревшего декодирования. (Или, когда непрямое выполнение микрокода для команды, которая занимает более 4 мопов, достигает передней части IDQ, выпускает / переименовывает выборки непосредственно из ПЗУ секвенсора микрокода для таких инструкций, как rep movsb
или lock cmpxchg
.)
Но когда у сцены нет входных данных, да, она отключается. Нет "спин-блокировки"; он не управляет эксклюзивным доступом к общему ресурсу, он просто ожидает на основе сигнала управления потоком.
Это также происходит, когда выборка кода попадает в кэш UOP: устаревшие декодеры также могут отключаться. Энергосбережение является одним из преимуществ кэша UOP и энергосберегающего буфера обратной связи для кэша UOP.
Контроллер кэша L1I выделяет буфер заполнения строки
L2-> L1i использует буферы, отличные от 10 LFB, которые используют кэш-память L1d / хранилища NT. Эти 10 предназначены для связи между L1d и L2.
Блок-схема Skylake-SP на WikiChip показывает 64-байтовый тракт данных от L2 до L1i, отдельный от L2-> L1d с его 10 LFB.
L2 должен управлять наличием нескольких устройств чтения и записи (кэши L1 и данные в / из L3 в его буферах SuperQueue). @ HadiBrais комментирует о том, что мы знаем, что L2 может обрабатывать 2 попадания за такт, но количество пропусков за такт, за которое он может обрабатывать / генерировать запросы L3, менее ясно.
Хади также прокомментировал: L2 имеет один считывающий 64-байтовый порт для L1i и один двунаправленный 64-байтовый порт с L1d. Он также имеет порт для чтения / записи (64-байтовый в Skylake, 32-байтовый в Haswell) со срезом L3, к которому он подключен. Когда контроллер L2 получает строку от L3, он немедленно записывает ее в соответствующую запись (или записи) супер очереди.
Я не проверил первоисточник для этого, но мне это кажется правильным.
Извлечение из DRAM происходит с пакетной передачей 64 байтов (1 строка кэша) за один раз . Не только 16 байтов (128 бит)! Можно выполнить код из «не кэшируемой» области памяти, но обычно вы используете области памяти WB (с обратной записью), которые можно кэшировать.
AFAIK, даже DDR4 имеет размер пакета 64 байта, а не 128 байтов.
Я предполагаю, что все это хранится в порядке очереди, поэтому домашний агент знает, какому адресу соответствуют данные.
Нет, контроллер памяти может переупорядочивать запросы на локальность на странице DRAM (не то же самое, что страница виртуальной памяти).
Данные, возвращающиеся в иерархию памяти, имеют связанный с ними адрес . Он кэшируется L3 и L2, потому что у них есть политика кэширования записи-выделения.
Когда он достигает L2, буфер ожидающих запросов (от L1i) совпадает с адресом, поэтому L2 пересылает эту строку в L1i. Который, в свою очередь, совпадает с адресом и пробуждает ожидающую логику выборки инструкций.
@ HadiBrais прокомментировал: запросы в L2 должны быть помечены идентификатором отправителя. Запросы в L3 должны быть помечены еще одним идентификатором отправителя. Запросы на L1I не должны быть помечены.
Хади также обсудил тот факт, что L3 должен обрабатывать запросы от нескольких ядер за цикл. Архитектура кольцевой шины в центральных процессорах до Skylake-SP / SKX означала, что максимум 3 запроса могли приходить на один срез L3 за такт (по одному в каждом направлении на кольце и один от подключенного к нему ядра). Если бы они все были для одной и той же строки кэша, было бы определенно выгодно удовлетворить их всех одной выборкой из этого среза, так что это может быть то, что делают срезы кэш-памяти L3.
См. Также Ульрих Дреппер Что каждый программист должен знать о памяти? , чтобы узнать больше о кеше и особенно о DDR DRAM. Статья Wikipedia SDRAM также объясняет, как работают пакетные передачи целых строк кэша от DRAM .
Я не уверен, действительно ли процессоры Intel передают смещение в пределах строки кэша для критического первого слова и раннего перезапуска для резервного копирования иерархии кэша. Думаю, нет, потому что некоторые из ближайших к ядру путей данных намного шире, чем 8 байтов, а в Skylake - 64 байта.
См. Также микроарху Agner Fog pdf (https://agner.org/optimize/), и другие ссылки в вики-теге x86 .