Механизм когерентности кэшей
Когерентность кэшей — это свойство системы кэширования, обеспечивающее согласованность данных, хранящихся в нескольких кэшах, с данными в основной памяти, а также между собой. В многопроцессорных и многоядерных системах, где каждый процессор или ядро имеет собственный кэш, механизмы когерентности предотвращают ситуацию, когда один процессор изменяет данные в своём кэше, а другой процессор продолжает использовать устаревшую копию тех же данных в своём кэше. Без когерентности кэшей корректность выполнения параллельных программ нарушается, что приводит к ошибкам вычислений. Механизмы когерентности реализуются на аппаратном уровне с помощью специальных протоколов и являются фундаментальной частью архитектуры современных микропроцессоров.
История и предпосылки
С развитием многопроцессорных систем в 1980-х годах возникла проблема согласования данных между кэшами. Первые коммерческие многопроцессорные машины, такие как Sequent Balance и Encore Multimax, использовали общую шину для связи между процессорами и памятью, что делало возможным реализацию простых протоколов когерентности. В 1983 году Джеймс Арчбальд и Роберт Баер ввели термин «когерентность кэшей» и формализовали требования к ней. Ключевой вехой стала разработка протокола MESI (Modified, Exclusive, Shared, Invalid) в 1983 году, который стал основой для большинства современных протоколов. В 1990-х годах с ростом числа ядер в одном процессоре механизмы когерентности стали внедряться и в однопроцессорных многоядерных системах, таких как Intel Pentium Pro и AMD K6. В 2000-х годах с появлением многопоточных процессоров и систем на кристалле (SoC) проблема когерентности стала ещё более актуальной, что привело к разработке протоколов для неоднородных архитектур, например, ARM AMBA CHI.
Основные проблемы и требования
Когерентность кэшей решает три фундаментальные проблемы:
- Проблема согласованности записи: Когда один процессор записывает данные в свой кэш, другие процессоры должны видеть это изменение. Если запись не видна, возникает состояние гонки.
- Проблема согласованности чтения: Когда процессор читает данные, он должен получить самую последнюю версию, даже если она находится в кэше другого процессора.
- Проблема последовательности операций: Порядок операций записи и чтения, выполняемых разными процессорами, должен быть определённым, чтобы избежать неопределённости в результатах.
Для обеспечения когерентности система должна удовлетворять следующим требованиям:
- Согласованность: Любое чтение из ячейки памяти возвращает последнее записанное в неё значение.
- Последовательность: Операции записи в одну и ту же ячейку памяти выполняются в порядке, определённом программой.
- Валидность: Кэш-линия, помеченная как валидная, содержит актуальные данные.
Протоколы когерентности кэшей
Протоколы когерентности определяют набор правил, по которым кэши обмениваются информацией о состоянии своих строк. Они делятся на два основных класса: протоколы на основе отслеживания (snooping) и протоколы на основе каталогов (directory-based).
Протоколы на основе отслеживания (Snooping Protocols)
В протоколах на основе отслеживания каждый кэш-контроллер «прослушивает» (snoops) общую шину или кольцо, по которому передаются все транзакции памяти. Когда один кэш-контроллер выполняет операцию (например, чтение или запись), он транслирует её на шину, и все остальные контроллеры проверяют, не хранят ли они копию запрашиваемой строки. Если да, они выполняют соответствующие действия (например, аннулируют свою копию или предоставляют данные).
Основные протоколы на основе отслеживания:
- MSI (Modified, Shared, Invalid): Простейший протокол. Строка может быть в состоянии Modified (изменена только в этом кэше), Shared (копия есть в нескольких кэшах, данные актуальны) или Invalid (недействительна). При записи в строку, находящуюся в состоянии Shared, все остальные копии аннулируются.
- MESI (Modified, Exclusive, Shared, Invalid): Добавляет состояние Exclusive (копия есть только в этом кэше, данные совпадают с памятью). Это позволяет избежать лишнего оповещения на шине при записи в строку, которая не была скопирована другими кэшами. MESI является стандартом для x86-совместимых процессоров.
- MOESI (Modified, Owned, Exclusive, Shared, Invalid): Добавляет состояние Owned (копия есть в этом кэше, она изменена, но другие кэши могут иметь устаревшие копии). Это позволяет кэшу, владеющему строкой, предоставлять данные другим кэшам без обращения к основной памяти, ускоряя передачу.
- MESIF (Modified, Exclusive, Shared, Invalid, Forward): Используется в процессорах Intel начиная с архитектуры Nehalem. Добавляет состояние Forward, которое указывает, что данный кэш является единственным, кто может предоставить копию строки другим кэшам, что снижает нагрузку на шину при широковещательных запросах.
Преимущества: Простота реализации, низкая задержка для небольших систем (до 4-8 процессоров). Недостатки: Плохая масштабируемость — каждая транзакция транслируется всем кэшам, что создаёт большую нагрузку на шину и ограничивает число процессоров.
Протоколы на основе каталогов (Directory-Based Protocols)
В протоколах на основе каталогов центральный каталог (directory) хранит информацию о том, какие кэши содержат копии каждой строки памяти. Когда процессор хочет выполнить операцию, он обращается к каталогу, который направляет запрос только тем кэшам, которые имеют копию строки. Это устраняет широковещательную рассылку.
Основные протоколы на основе каталогов:
- Полностью ассоциативный каталог: Каждая запись каталога хранит битовую маску, указывающую, какие кэши имеют копию строки. Требует много памяти, но обеспечивает быстрый доступ.
- Ограниченный каталог: Каждая запись каталога хранит только ограниченное число указателей (например, 2-4). Если число кэшей, содержащих копию, превышает лимит, используется широковещательная рассылка. Более экономичен, чем полностью ассоциативный.
- Иерархический каталог: Используется в больших системах с многоуровневой иерархией кэшей. Каталог на каждом уровне хранит информацию о кэшах нижележащего уровня.
Преимущества: Хорошая масштабируемость — нагрузка на сеть растёт пропорционально числу кэшей, а не квадратично. Используется в системах с большим числом процессоров (сотни и тысячи). Недостатки: Более сложная реализация, дополнительная задержка на обращение к каталогу, повышенное потребление памяти.
Классификация механизмов когерентности
Помимо протоколов, механизмы когерентности можно классифицировать по способу обеспечения согласованности:
- Write-invalidate (Запись с аннулированием): При записи в строку все остальные копии этой строки в других кэшах аннулируются. Это наиболее распространённый подход, используемый в протоколах MESI, MOESI. При следующем чтении аннулированной строки кэш выполняет промах и загружает новую копию.
- Write-update (Запись с обновлением): При записи в строку все остальные копии этой строки обновляются новым значением. Этот подход реже используется из-за высокой нагрузки на шину, но может быть эффективен в некоторых сценариях (например, при частом чтении обновляемых данных).
Реализация в современных процессорах
В современных процессорах (Intel Core, AMD Ryzen, ARM Cortex) механизмы когерентности реализованы аппаратно на уровне кэш-контроллера. В многоядерных процессорах обычно используется протокол MESI или его расширения (MESIF, MOESI). В системах с несколькими процессорами (многопроцессорные серверы) часто применяются протоколы на основе каталогов, реализованные в чипсете или встроенном контроллере памяти.
Например, в процессорах Intel Core используется протокол MESIF, где состояние Forward позволяет одному кэшу предоставлять данные другим без обращения к памяти. В процессорах AMD Ryzen применяется протокол MOESI. В мобильных процессорах ARM Cortex-A часто используется протокол MOESI с поддержкой когерентности между ядрами и GPU.
Когерентность в неоднородных системах (Heterogeneous Coherence)
С ростом популярности гетерогенных вычислительных систем (например, SoC с CPU, GPU, DSP, NPU) возникла необходимость в когерентности между различными типами ядер. Для этого разработаны протоколы, такие как ARM AMBA CHI (Coherent Hub Interface) и Intel QuickPath Interconnect (QPI). Эти протоколы обеспечивают когерентность между кэшами CPU, GPU и других ускорителей, что позволяет эффективно обмениваться данными без копирования через основную память.
Критика и ограничения
- Сложность реализации: Протоколы когерентности требуют сложной аппаратной логики, что увеличивает площадь кристалла и энергопотребление.
- Проблемы с масштабируемостью: Протоколы на основе отслеживания плохо масштабируются из-за широковещательной рассылки. Протоколы на основе каталогов требуют значительных ресурсов для хранения каталогов.
- Задержки: Каждая операция когерентности (аннулирование, обновление) вносит дополнительную задержку, что может снижать производительность в некоторых сценариях.
- Проблема «ложного разделения» (False Sharing): Когда два процессора работают с разными данными, но эти данные находятся в одной кэш-линии, система когерентности может аннулировать строку при каждом изменении, что приводит к избыточным промахам кэша и снижению производительности.
- Энергопотребление: Аппаратные механизмы когерентности потребляют значительную энергию, особенно в протоколах на основе отслеживания, где каждый кэш-контроллер постоянно прослушивает шину.
Интересные факты
- Первый протокол когерентности кэшей был реализован в суперкомпьютере Cray X-MP в 1982 году.
- Протокол MESI был разработан в 1983 году группой исследователей из Университета Иллинойса.
- В процессорах Intel Pentium Pro использовался протокол MESI, который стал первым коммерческим протоколом когерентности для x86-архитектуры.
- Современные процессоры могут иметь до 8-12 уровней кэша (L1, L2, L3, L4), каждый из которых участвует в протоколе когерентности.
- В некоторых суперкомпьютерах (например, IBM Blue Gene) используются специальные протоколы когерентности, оптимизированные для работы с тысячами процессоров.
Источники
- Архитектура компьютерных систем. Таненбаум Э., Остин Т. (2017)
- Организация ЭВМ и систем. Паттерсон Д., Хеннесси Дж. (2018)
- Cache Coherence Protocols. David A. Patterson, John L. Hennessy (2011)
- A Primer on Memory Consistency and Cache Coherence. Daniel J. Sorin, Mark D. Hill, David A. Wood (2011)
- Intel 64 and IA-32 Architectures Software Developer’s Manual (2023)
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →