В архитектуре компьютера когерентность кэша — это однородность данных общих ресурсов, которые в конечном итоге сохраняются в нескольких локальных кэшах . Когда клиенты в системе поддерживают кэши общего ресурса памяти, могут возникнуть проблемы с некогерентными данными, что особенно актуально для ЦП в многопроцессорной системе.
На иллюстрации справа предположим, что у обоих клиентов есть кэшированная копия определенного блока памяти из предыдущего чтения. Предположим, что клиент внизу обновляет/изменяет этот блок памяти, клиент вверху может остаться с недействительным кэшем памяти без уведомления об изменении. Согласованность кэша предназначена для управления такими конфликтами путем поддержания согласованного представления значений данных в нескольких кэшах.
В многопроцессорной системе с общей памятью и отдельной кэш-памятью для каждого процессора возможно иметь много копий общих данных: одну копию в основной памяти и одну в локальном кэше каждого процессора, который запросил ее. Когда одна из копий данных изменяется, другие копии должны отражать это изменение. Согласованность кэша — это дисциплина, которая гарантирует, что изменения значений общих операндов (данных) своевременно распространяются по всей системе. [1]
Ниже приведены требования к согласованности кэша: [2]
Теоретически, когерентность может быть выполнена на уровне гранулярности загрузки/сохранения . Однако на практике она обычно выполняется на уровне гранулярности блоков кэша. [3]
Согласованность определяет поведение операций чтения и записи по одному адресу. [2]
Один из типов данных, которые одновременно хранятся в разных кэш-памяти, называется когерентностью кэша или, в некоторых системах, глобальной памятью.
В многопроцессорной системе предположим, что более одного процессора кэшируют копию ячейки памяти X. Для достижения согласованности кэша необходимы следующие условия: [4]
Вышеуказанные условия удовлетворяют критериям Write Propagation, необходимым для когерентности кэша. Однако они недостаточны, поскольку не удовлетворяют условию Transaction Serialization. Чтобы лучше проиллюстрировать это, рассмотрим следующий пример:
Многопроцессорная система состоит из четырех процессоров - P1, P2, P3 и P4, все из которых содержат кэшированные копии общей переменной S, начальное значение которой равно 0. Процессор P1 изменяет значение S (в своей кэшированной копии) на 10, после чего процессор P2 изменяет значение S в своей собственной кэшированной копии на 20. Если мы обеспечим только распространение записи, то P3 и P4 наверняка увидят изменения, внесенные в S P1 и P2. Однако P3 может увидеть изменение, внесенное P1, после того, как увидит изменение, внесенное P2, и, следовательно, вернуть 10 при чтении в S. P4, с другой стороны, может увидеть изменения, внесенные P1 и P2 в том порядке, в котором они были сделаны, и, следовательно, вернуть 20 при чтении в S. Процессоры P3 и P4 теперь имеют несогласованное представление памяти.
Таким образом, для удовлетворения требований сериализации транзакций и, следовательно, достижения согласованности кэша необходимо выполнить следующее условие наряду с двумя предыдущими, упомянутыми в этом разделе:
Альтернативное определение когерентной системы осуществляется через определение модели памяти последовательной согласованности : «система последовательной согласованности кэша должна выполнять загрузку и сохранение всех потоков в одну ячейку памяти в общем порядке, который учитывает порядок программы каждого потока». [3] Таким образом, единственное различие между системой последовательной согласованности кэша и системой последовательной согласованности заключается в количестве адресных ячеек, о которых говорится в определении (одна ячейка памяти для системы последовательной согласованности кэша и все ячейки памяти для системы последовательной согласованности).
Другое определение: «мультипроцессор является кэш-консистентным, если все записи в одну и ту же область памяти выполняются в некотором последовательном порядке». [6]
Редко, но особенно в алгоритмах, когерентность может вместо этого относиться к локальности ссылки . Несколько копий одних и тех же данных могут существовать в разных кэшах одновременно, и если процессорам разрешено свободно обновлять свои собственные копии, это может привести к несогласованному представлению памяти.
Два наиболее распространенных механизма обеспечения согласованности — это снупинг и основанный на каталогах , каждый из которых имеет свои преимущества и недостатки. [7] Протоколы, основанные на снупинге, как правило, быстрее, если доступна достаточная пропускная способность , поскольку все транзакции представляют собой запрос/ответ, видимый всеми процессорами. Недостатком является то, что снупинг не масштабируется. Каждый запрос должен транслироваться на все узлы в системе, а это означает, что по мере увеличения системы размер (логической или физической) шины и предоставляемая ею пропускная способность должны расти. Каталоги, с другой стороны, имеют тенденцию иметь более длительные задержки (с 3-х сквозным запросом/пересылкой/ответом), но используют гораздо меньшую пропускную способность, поскольку сообщения передаются по принципу точка-точка, а не транслируются. По этой причине многие из более крупных систем (>64 процессоров) используют этот тип согласованности кэша.
Распределенные системы общей памяти имитируют эти механизмы, пытаясь сохранить согласованность между блоками памяти в слабосвязанных системах. [10]
Протоколы когерентности применяют когерентность кэша в многопроцессорных системах. Цель состоит в том, чтобы два клиента никогда не видели разные значения для одних и тех же общих данных.
Протокол должен реализовывать основные требования к согласованности. Он может быть адаптирован для целевой системы или приложения.
Протоколы также можно классифицировать как отслеживающие или основанные на каталогах. Обычно ранние системы использовали протоколы на основе каталогов, где каталог отслеживал данные, которыми обмениваются, и их участников. В протоколах отслеживания запросы на транзакции (на чтение, запись или обновление) отправляются всем процессорам. Все процессоры отслеживают запрос и отвечают соответствующим образом.
Распространение записи в протоколах слежения может быть реализовано одним из следующих методов:
Если в проекте протокола указано, что всякий раз, когда изменяется какая-либо копия общих данных, все остальные копии должны быть «обновлены» для отражения изменения, то это протокол записи-обновления. Если в проекте указано, что запись в кэшированную копию любым процессором требует, чтобы другие процессоры отбросили или сделали недействительными свои кэшированные копии, то это протокол записи-недействителен.
Однако масштабируемость является одним из недостатков широковещательных протоколов.
Для поддержания когерентности были разработаны различные модели и протоколы, такие как MSI , MESI (он же Illinois), MOSI , MOESI , MERSI , MESIF , write-once , Synapse, Berkeley, Firefly и Dragon protocol . [1] В 2011 году ARM Ltd предложила AMBA 4 ACE [11] для управления когерентностью в SoC . Спецификация AMBA CHI (Coherent Hub Interface) [12] от ARM Ltd , которая принадлежит к группе спецификаций AMBA5, определяет интерфейсы для подключения полностью когерентных процессоров.