Почему размер кэша L1 меньше, чем размер кэша L2 в большинстве процессоров?
Почему размер кэша L1 меньше, чем размер кэша L2 в большинстве процессоров?
7 ответов
Для этого есть разные причины.
L2 существует в системе, чтобы ускорить случай, когда происходит потеря кэша L1. Если бы размер L1 был таким же или больше, чем размер L2, то L2 не смог бы вместить больше строк кэша, чем L1, и не смог бы справиться с промахами кэша L1. С точки зрения дизайна / стоимости, кэш L1 связан с процессором и быстрее, чем L2. Основная идея кэшей заключается в том, что вы ускоряете доступ к более медленному оборудованию, добавляя промежуточное оборудование, которое является более производительным (и дорогим), чем самое медленное оборудование, и в то же время дешевле, чем имеющееся у вас более быстрое оборудование. Даже если вы решили удвоить кэш L1, вы также увеличите L2, чтобы ускорить промахи L1-кэша.
Так зачем вообще кеш L2? Что ж, кэш L1 обычно более производительный и дорогой для сборки, и он привязан к одному ядру. Это означает, что увеличение размера L1 на фиксированное количество приведет к умножению этой стоимости на 4 в двухъядерном процессоре или на 8 в четырехъядерном процессоре. Уровень L2 обычно используется разными ядрами - в зависимости от архитектуры он может быть распределен между парой или всеми ядрами процессора, поэтому стоимость увеличения уровня L2 будет меньше, даже если цены на L1 и L2 будут одинаковыми, что это не.
L1 очень тесно связан с ядром ЦП и доступен при каждом доступе к памяти (очень часто). Таким образом, он должен возвращать данные очень быстро (обычно в течение тактового цикла). Задержка и пропускная способность (полоса пропускания) являются критичными для производительности для кэша данных L1. (например, задержка в четыре цикла и поддержка двух операций чтения и одной записи ядром ЦП каждый такт). Для поддержки этой высокой пропускной способности требуется много портов чтения / записи. Создание большого кэша с этими свойствами невозможно. Таким образом, дизайнеры держат его небольшим, например 32 КБ в большинстве процессоров сегодня.
Доступ к L2 возможен только при пропусках L1, поэтому доступ осуществляется реже (обычно 1/20 от L1). Таким образом, L2 может иметь большую задержку (например, от 10 до 20 циклов) и иметь меньше портов. Это позволяет дизайнерам сделать его больше.
L1 и L2 играют очень разные роли. Если L1 будет увеличен, это увеличит задержку доступа к L1, что резко снизит производительность, потому что это сделает все зависимые нагрузки медленнее и сложнее для скрытого выполнения. Размер L1 практически не обсуждается.
Если мы удалили L2, промахи L1 должны будут перейти на следующий уровень, скажем, в память. Это означает, что большой объем доступа будет поступать в память, что будет означать, что нам нужна дополнительная пропускная способность памяти, что уже является узким местом. Таким образом, держать L2 вокруг это выгодно.
Эксперты часто называют L1 фильтром задержки (поскольку это ускоряет общий случай попаданий L1) и L2 как фильтр полосы пропускания, так как он уменьшает использование полосы пропускания памяти.
Примечание. Я использовал двухуровневую иерархию кэша в своем аргументе, чтобы упростить его. Во многих современных многоядерных чипах кэш-память L3 совместно используется всеми ядрами, в то время как каждое ядро имеет свой собственный L1 и, возможно, L2. В этих чипах общий кэш последнего уровня (L3) играет роль фильтра пропускной способности памяти. L2 играет роль фильтра пропускной способности внутри кристалла, то есть он уменьшает доступ к межсоединению внутри кристалла и L3. Это позволяет разработчикам использовать межсоединение с более низкой пропускной способностью, например, кольцо, и медленный однопортовый L3, что позволяет им увеличить L3.
Возможно, стоит упомянуть, что количество портов является очень важным моментом проектирования, поскольку оно влияет на то, сколько чипа занимает кэш-память. Порты добавляют провода в кеш, который потребляет много микросхемы и энергии.
Ответ @Aater объясняет некоторые основы. Я добавлю еще несколько деталей + примеры реальной организации кэша на Intel Haswell и AMD Piledriver с задержками и другими свойствами, а не только размером.
Некоторые подробности о IvyBridge см. В моем ответе на тему "Как кэширование может быть таким быстрым?" с некоторым обсуждением общей задержки использования нагрузки, включая время вычисления адреса и ширину шин данных между различными уровнями кэша.
L1 должен быть очень быстрым (задержка и пропускная способность), даже если это означает ограниченную частоту попаданий. L1d также должен поддерживать однобайтовые хранилища практически на всех архитектурах и (в некоторых конструкциях) не выравниваемый доступ. Это затрудняет использование ECC (кодов исправления ошибок) для защиты данных, и на самом деле некоторые модели L1d (Intel) просто используют четность, с лучшим ECC только на внешних уровнях кэша (L2/L3), где можно использовать ECC на больших кусках для более низких накладных расходов.
Невозможно спроектировать один уровень кеша, который мог бы обеспечить низкую среднюю задержку запросов (усредненную по всем ударам и пропускам) современного многоуровневого кеша. Поскольку современные системы имеют несколько очень "голодных" ядер, и все они совместно используют одно и то же DRAM с относительно высокой задержкой, это очень важно.
Каждому ядру нужен собственный частный L1 для скорости, но, по крайней мере, последний уровень кеша обычно используется совместно, поэтому многопоточная программа, которая считывает одни и те же данные из нескольких потоков, не должна обращаться к DRAM для каждого ядра. (И выступать в качестве поддержки для данных, записанных одним ядром и прочитанных другим). Это требует как минимум двух уровней кеша для нормальной многоядерной системы и является частью мотивации для более чем двух уровней в современных разработках. Современные многоядерные процессоры x86 имеют быстрый двухуровневый кеш в каждом ядре и более медленный кеш, общий для всех ядер.
Частота обращений к L1 по-прежнему очень важна, поэтому кэши L1 не так малы / просты / быстры, как могли бы быть, потому что это уменьшит частоту попаданий. Таким образом, достижение такой же общей производительности потребует более высоких уровней кэша, чтобы быть быстрее. Если более высокие уровни обрабатывают больше трафика, их задержка является большей составляющей средней задержки, и они чаще ограничивают свою пропускную способность (или нуждаются в более высокой пропускной способности).
Высокая пропускная способность часто означает возможность обрабатывать несколько операций чтения и записи в каждом цикле, то есть нескольких портов. Это требует больше площади и мощности для той же емкости, что и кэш с более низкой пропускной способностью, поэтому это еще одна причина, по которой L1 остается небольшим.
L1 также использует трюки скорости, которые не сработали бы, если бы они были больше. т. е. большинство проектов используют виртуально индексированный, физически помеченный (VIPT) L1, но со всеми битами индекса, идущими снизу от смещения страницы, поэтому они ведут себя как PIPT (потому что младшие биты виртуального адреса такие же, как в физическом адресе), Это позволяет избежать синонимов / омонимов (ложные попадания или одни и те же данные в кеше дважды, и увидеть подробный ответ Пола Клэйтона на связанный вопрос), но все же позволяет выполнять проверку совпадений / совпадений параллельно с поиском TLB. Кешу VIVT не нужно ждать TLB, но он должен быть недействительным при каждом изменении таблиц страниц.
На платформе x86 (которая использует страницы виртуальной памяти размером 4 КБ) 8-разрядные ассоциативные кэши L132 КБ распространены в современных разработках. Эти 8 тегов могут быть выбраны на основе младших 12 битов виртуального адреса, потому что эти биты одинаковы в виртуальных и физических адресах (они ниже смещения страницы для страниц размером 4 КБ). Этот скачок скорости для кэшей L1 работает, только если они достаточно малы и достаточно ассоциативны, чтобы индекс не зависел от результата TLB. 32киБ / 64В линий / 8-полосная ассоциативность = 64 (2^6) комплектов. Таким образом, младшие 6 бит адреса выбирают байты в строке, а следующие 6 бит индексируют набор из 8 тегов. Этот набор из 8 тегов выбирается параллельно с поиском TLB, поэтому теги можно параллельно проверять по битам выбора физической страницы результата TLB, чтобы определить, какой (если есть) из 8 способов кэширования хранить данные,
Создание большего кеша L1 означало бы, что ему нужно либо дождаться результата TLB, прежде чем он сможет даже начать выбирать теги и загружать их в параллельные компараторы, либо увеличить ассоциативность, чтобы сохранить log2(sets) + log2(line_size) <= 12. (Больше ассоциативности означает больше путей на набор => меньше общих наборов = меньше индексных битов). Так, например, кэш-память размером 64 КБ должна быть ассоциативной с 16 путями: по-прежнему 64 набора, но каждый набор имеет в два раза больше способов. Это делает увеличение размера L1 сверх текущего размера чрезмерно дорогим с точки зрения мощности и, возможно, даже задержки.
Если вы потратите больше своего энергопотребления на логику кэша L1D, то останется меньше энергии для выполнения не по порядку выполнения, декодирования и, конечно, кэша L2 и так далее. Чтобы все ядро работало на частоте 4 ГГц и выдерживало ~4 команды в такт (для кода с высоким ILP) без плавления, требуется сбалансированный дизайн. Смотрите эту статью: Современные микропроцессоры: руководство за 90 минут!,
Чем больше кэш, тем больше вы теряете при его очистке, поэтому большой кэш VIVT L1 будет хуже, чем текущий VIPT, который работает как PIPT. И больший, но с большим временем ожидания L1D, вероятно, также будет хуже.
Согласно @PaulClayton, кэши L1 часто извлекают все данные в наборе параллельно с тегами, поэтому они готовы для выбора после обнаружения правильного тега. Затраты на электроэнергию для этого масштабируются с ассоциативностью, поэтому большой высокоассоциативный L1 будет очень плох для энергопотребления, а также для площади кристалла (и задержки). (По сравнению с L2 и L3 площадь не будет большой, но для латентности важна физическая близость. Задержка распространения скорости света имеет значение, когда тактовые импульсы составляют 1/4 наносекунды.)
Более медленные кэши (например, L3) могут работать при более низком напряжении / тактовой частоте, чтобы выделять меньше тепла. Они могут даже использовать различные схемы расположения транзисторов для каждой ячейки памяти, чтобы сделать память более оптимизированной для питания, чем для высокой скорости.
Существует много причин, связанных с использованием мощности, для многоуровневых кэшей. Мощность / тепло является одним из наиболее важных ограничений в современном дизайне процессора, потому что охлаждение крошечного чипа затруднительно. Все является компромиссом между скоростью и мощностью (и / или площадью кристалла). Кроме того, многие процессоры питаются от батарей или находятся в дата-центрах, которые нуждаются в дополнительном охлаждении.
L1 почти всегда разделяется на отдельные кеши команд и данных. Вместо дополнительного порта чтения в унифицированном L1 для поддержки выборки кода мы можем иметь отдельный кэш L1I, связанный с отдельным I-TLB. (Современные ЦП часто имеют L2-TLB, который является вторым уровнем кеша для переводов, совместно используемым L1 I-TLB и D-TLB, а не TLB, используемым обычным кешем L2). Это дает нам общий объем кэш-памяти L1 размером 64 КБ, статически разделенный на кэш-память кода и данных, за гораздо более дешевую (и, возможно, более низкую задержку), чем унифицированный кэш-память L1 размером 64 КБ с той же общей пропускной способностью. Поскольку между кодом и данными обычно очень мало совпадений, это большой выигрыш.
L1I может быть размещен физически близко к логике выборки кода, в то время как L1D может быть физически близко к блокам загрузки / сохранения. Задержки линии передачи со скоростью света имеют большое значение, когда тактовый цикл длится всего 1/3 наносекунды. Маршрутизация проводки также имеет большое значение: например, Intel Broadwell имеет 13 слоев меди над кремнием.
Сплит L1 очень помогает со скоростью, но унифицированный L2 - лучший выбор. Некоторые рабочие нагрузки имеют очень маленький код, но касаются большого количества данных. Имеет смысл объединить кэши более высокого уровня для адаптации к различным рабочим нагрузкам вместо статического разделения на код и данные. (Например, почти весь L2 будет кешировать данные, а не код при выполнении большого умножения матриц, в отличие от большого количества горячего кода при выполнении раздутой программы на C++ или даже эффективной реализации сложного алгоритма (например, при запуске gcc).). Код можно копировать как данные, а не всегда просто загружать с диска в память с помощью DMA.
Кэшам также нужна логика для отслеживания невыполненных пропусков (поскольку выполнение по порядку означает, что новые запросы могут продолжать генерироваться до разрешения первого пропуска). Наличие большого количества пропущенных пропусков означает, что вы перекрываете задержку пропусков, достигая более высокой пропускной способности. Дублирование логики и / или статическое разделение между кодом и данными в L2 не было бы хорошо.
Большие кэши с меньшим трафиком также являются хорошим местом для размещения логики предварительной выборки. Аппаратная предварительная выборка обеспечивает хорошую производительность для таких вещей, как зацикливание массива, при этом каждому коду не требуются инструкции предварительной программной выборки. (Предварительная выборка SW была важна некоторое время, но предварительные выборки HW умнее, чем раньше, так что советы Ульриха Дреппера в остальном превосходны " Что должен знать каждый программист о памяти" для многих случаев использования устарели.)
Кэши высокого уровня с низким трафиком могут позволить задержке делать умные вещи, такие как использование политики адаптивной замены вместо обычного LRU. Intel IvyBridge и более поздние процессоры делают это, чтобы противостоять шаблонам доступа, которые не получают попаданий в кэш для рабочего набора, чуть слишком большого для размещения в кеше. (Например, повторение нескольких данных в одном и том же направлении дважды означает, что они, вероятно, будут выселены непосредственно перед повторным использованием.)
Реальный пример: Intel Haswell. Источники: анализ микроархитектуры Дэвида Кантера и результаты тестирования Agner Fog (microarch pdf). См. Также руководства по оптимизации Intel (ссылки в теге x86 вики).
Кроме того, я написал отдельный ответ на вопрос: Какая техника отображения кэша используется в процессоре Intel Core i7?
В современных разработках Intel используется большой инклюзивный кэш L3, который используется всеми ядрами, в качестве опоры для трафика когерентности кэша. Он физически распределен между ядрами с 2048 наборами * 16-полосной (2 МБ) на ядро (с адаптивной политикой замены в IvyBridge и более поздних версиях).
Нижние уровни кэша для каждого ядра.
- L1: для каждого ядра 32 кБ каждая инструкция и данные (разделенные), 8-сторонняя ассоциативная. Задержка = 4 цикла. Как минимум 2 порта чтения + 1 порт записи. ( Может быть, даже больше портов для обработки трафика между L1 и L2, или, возможно, получение строки кэша от L2 конфликтует с удалением магазина.) Может отслеживать 10 невыполненных кеш-пропусков (10 буферов заполнения).
- L2: унифицированный на ядро 256 кБ, 8-сторонняя ассоциативная. Задержка = 11 или 12 циклов. Пропускная способность чтения: 64 байта / цикл. Основная логика предварительной выборки выполняет предварительную выборку в L2. Может отслеживать 16 выдающихся промахов. Может поставлять 64B за цикл к L1I или L1D. Фактический порт считается неизвестным.
- L3: унифицированный, общий (по всем ядрам) 8MiB (для четырехъядерного i7). Включено (из всех кешей L2 и L1 на ядро). 12 или 16 способ ассоциативный. Задержка = 34 цикла. Выступает в качестве поддержки для когерентности кэша, поэтому измененные общие данные не должны выходить в основную память и обратно.
Другой реальный пример: AMD Piledriver: (например, процессоры Opteron и настольные FX). Размер строки кэша по-прежнему составляет 64B, как Intel и AMD используют уже несколько лет. Текст в основном скопирован из pdf-файла Agner Fog с дополнительной информацией о некоторых найденных мною слайдах и более подробной информацией о сквозном кеше L1 + 4k для записи в блоге Агнера с комментарием о том, что только L1 - это WT, а не L2.
- L1I: 64 кБ, двухсторонняя, совместно используемая парой ядер (версия SMD AMD имеет более статическое разбиение, чем Hyperthreading, и они называют каждое ядром. Каждая пара совместно использует модуль вектора / FPU и другие ресурсы конвейера.)
- L1D: 16 кБ, 4-полосная, на ядро. Задержка = 3-4 с. (Обратите внимание, что все 12 битов ниже смещения страницы все еще используются для индексации, поэтому обычный трюк VIPT работает.) (Пропускная способность: две операции за такт, причем одна из них является хранилищем). Policy = Write-Through, с 4k-комбинированным кэшем записи.
- L2: 2 МБ, 16-полосная, распределяется между двумя ядрами. Задержка = 20 часов. Считайте пропускную способность 1 за 4 часа. Запись пропускной способности 1 на 12 часов.
- L3: 0 - 8 МБ, 64-полосная, используется всеми ядрами. Задержка = 87 часов. Считайте пропускную способность 1 на 15 часов. Производительность записи 1 за 21 час
Agner Fog сообщает, что с активными обоими ядрами пары пропускная способность L1 ниже, чем когда другая половина пары простаивает. Неизвестно, что происходит, поскольку кэш-память L1 должна быть отдельной для каждого ядра.
Другие ответы здесь дают конкретные и технические причины того, почему L1 и L2 имеют такой же размер, и, хотя многие из них являются мотивирующими соображениями для конкретных архитектур, они на самом деле не нужны: основное архитектурное давление ведет к увеличению (частного) размера кэша. поскольку вы удаляетесь от ядра, он достаточно универсален и аналогичен рассуждениям о множественных кешах.
Три основных факта:
- Доступ к памяти для большинства приложений демонстрирует высокую степень временной локализации с неравномерным распределением.
- В широком спектре процессов и конструкций размер и скорость кеша (задержка и пропускная способность) могут быть соотнесены друг с другом 1.
- Каждый отдельный уровень кэша включает дополнительные затраты на проектирование и производительность.
Таким образом, на базовом уровне вы можете сказать удвоить размер кэша, но понизить штраф за задержку в 1,4 раза по сравнению с меньшим размером кэша.
Таким образом, это становится проблемой оптимизации: сколько кешей у вас должно быть и сколько их должно быть? Если бы доступ к памяти был абсолютно равномерным в пределах рабочего размера набора, вы, вероятно, в конечном итоге получили бы один довольно большой кэш или вообще никакого кеша. Тем не менее, доступ сильно неоднороден, поэтому небольшой и быстрый кэш может захватывать большое количество обращений, непропорционально его размеру.
Если бы факт 2 не существовал, вы бы просто создали очень большой и очень быстрый кэш L1 в рамках других ограничений вашего чипа и не нуждались в других уровнях кеша.
Если бы факт 3 не существовал, вы бы получили огромное количество мелкозернистых "кэшей", быстрее и меньше в центре и медленнее и больше снаружи, или, возможно, один кэш с переменным временем доступа: быстрее для части, наиболее близкие к ядру. На практике правило 3 означает, что каждый уровень кэша имеет дополнительную стоимость, поэтому вы обычно получаете несколько квантованных уровней кэша 2.
Другие ограничения
Это дает базовую основу для понимания количества и размера кэша, но есть и второстепенные факторы. Например, Intel x86 имеет размеры страниц 4K, а их кэши L1 используют архитектуру VIPT. VIPT означает, что размер кеша, деленный на количество способов, не может превышать 3 КиБ. Таким образом, 8-канальный кэш L1, используемый в полдюжине проектов Intel, может составлять максимум 4 КиБ * 8 = 32 КиБ. Вероятно, не случайно, что это именно тот размер кеша L1 в этих проектах! Если бы не это ограничение, вполне возможно, что вы видели бы более низкую ассоциативность и / или большие кэши L1 (например, 64 КиБ, 4-сторонние).
1 Конечно, есть и другие факторы, участвующие в обмене, такие как площадь и мощность, но при сохранении этих факторов постоянным применяется соотношение размера и скорости, и даже если оно не поддерживается постоянным, основное поведение остается тем же.
2 В дополнение к этому давлению есть преимущество в планировании для кэшей с известной задержкой, как и в большинстве проектов L1: и планировщик вне очереди может оптимизировать отправку операций, которые зависят от загрузки памяти в цикле, который вернет кэш L1, считывание результата с обходной сети. Это уменьшает конкуренцию и, возможно, сокращает цикл задержки от критического пути. Это оказывает некоторое давление на самый внутренний уровень кэша, чтобы иметь равномерную / предсказуемую задержку, и, вероятно, приводит к меньшему количеству уровней кэша.
3 В принципе, вы можете использовать VIPT-кеши без этого ограничения, но только требуя поддержки ОС (например, раскраски страниц) или с другими ограничениями. Арка x86 этого не сделала и, вероятно, не может начать сейчас.
Для тех, кто интересуется вопросами такого типа, мой университет рекомендует " Архитектура компьютера: количественный подход", " Организация и проектирование компьютеров: интерфейс аппаратного и программного обеспечения". Конечно, если у вас нет времени для этого, краткий обзор доступен в Википедии.
Я думаю, что основной причиной этого является то, что L1-кэш быстрее и поэтому дороже.
Логично, вопрос отвечает сам.
Если бы L1 был больше, чем L2 (вместе взятый), тогда не было бы необходимости в L2 Cache.
Зачем вам хранить свои вещи на ленточном накопителе, если вы можете хранить все это на жестком диске?