Bus snooping или bus sniffing — это схема, с помощью которой контроллер когерентности (snooper) в кэше ( snoopy cache ) отслеживает или отслеживает транзакции шины, и его цель — поддерживать когерентность кэша в распределенных системах с общей памятью . Эта схема была введена Равишанкаром и Гудманом в 1983 году под названием «write-once» cache coherency. [1] Кэш, содержащий контроллер когерентности (snooper), называется snoopy cache.
Когда определенные данные совместно используются несколькими кэшами, и процессор изменяет значение общих данных, изменение должно быть распространено на все остальные кэши, которые имеют копию данных. Такое распространение изменений предотвращает нарушение согласованности кэша системой . Уведомление об изменении данных может быть сделано с помощью отслеживания шины. Все отслеживатели отслеживают каждую транзакцию на шине. Если транзакция, изменяющая блок общего кэша, появляется на шине, все отслеживатели проверяют, имеют ли их кэши ту же копию общего блока. Если кэш имеет копию общего блока, соответствующий отслеживатель выполняет действие для обеспечения согласованности кэша. Действие может быть очисткой или аннулированием блока кэша. Оно также включает изменение состояния блока кэша в зависимости от протокола согласованности кэша. [2]
В зависимости от способа управления локальной копией операции записи существует два вида протоколов слежения:
Когда процессор записывает в общий блок кэша, все общие копии в других кэшах становятся недействительными посредством отслеживания шины. [3] Этот метод гарантирует, что только одна копия данных может быть эксклюзивно прочитана и записана процессором. Все остальные копии в других кэшах становятся недействительными. Это наиболее часто используемый протокол отслеживания. Протоколы MSI , MESI , MOSI , MOESI и MESIF относятся к этой категории.
Когда процессор записывает в общий блок кэша, все общие копии других кэшей обновляются посредством отслеживания шины. Этот метод транслирует данные записи во все кэши по всей шине. Он вызывает больший трафик шины, чем протокол write-invalidate. Вот почему этот метод не распространен. Протоколы Dragon и Firefly относятся к этой категории. [4] [5]
Одна из возможных реализаций выглядит следующим образом:
Кэш будет иметь три дополнительных бита :
Каждая строка кэша находится в одном из следующих состояний: «грязная» (обновлена локальным процессором), «действительная», «недействительная» или «общая». Строка кэша содержит значение, и его можно прочитать или записать. Запись в строку кэша изменяет значение. Каждое значение находится либо в основной памяти (доступ к которой очень медленный), либо в одном или нескольких локальных кэшах (что быстро). Когда блок впервые загружается в кэш, он помечается как «действительный».
При промахе чтения в локальном кэше запрос на чтение транслируется на шину. Все контроллеры кэша отслеживают шину. Если один из них кэшировал этот адрес и он находится в состоянии «грязный», он меняет состояние на «действительный» и отправляет копию запрашивающему узлу. Состояние «действительный» означает, что строка кэша является текущей. При локальном промахе записи (предпринята попытка записать это значение, но его нет в кэше) отслеживание шины гарантирует, что все копии в других кэшах будут установлены как «недействительные». «Недействительный» означает, что копия существовала в кэше, но больше не является текущей.
Например, начальное состояние может выглядеть так:
Тег | ID | V | D | S---------------------1111 | 00 | 1 | 0 | 00000 | 01 | 0 | 0 | 00000 | 10 | 1 | 0 | 10000 | 11 | 0 | 0 | 0
После записи адреса 1111 00 он изменится на следующий:
Тег | ID | V | D | S---------------------1111 | 00 | 1 | 1 | 00000 | 01 | 0 | 0 | 00000 | 10 | 1 | 0 | 10000 | 11 | 0 | 0 | 0
Логика кэширования отслеживает шину и определяет, запрашивается ли какая-либо кэшированная память. Если кэш грязный и общий, и на шине есть запрос на эту память, элемент грязного слежения предоставит данные запрашивающей стороне. В этот момент либо запрашивающая сторона может взять на себя ответственность за данные (отметив данные как грязные), либо память может захватить копию (говорят, что память «снарфицировала» данные), и два элемента переходят в общее состояние. [6]
При аннулировании адреса, помеченного как грязный (т.е. один кэш будет иметь грязный адрес, а другой кэш будет записывать), кэш проигнорирует этот запрос. Новый кэш будет помечен как грязный, действительный и исключительный, и этот кэш теперь будет нести ответственность за адрес. [1]
Преимущество использования отслеживания шины заключается в том, что оно быстрее, чем механизм согласованности на основе каталога . Данные, которые совместно используются, размещаются в общем каталоге, который поддерживает согласованность между кэшами в системе на основе каталога. Отслеживание шины обычно быстрее, если есть достаточная пропускная способность , поскольку все транзакции являются запросом/ответом, видимым всеми процессорами. [2]
Недостатком отслеживания шины является ограниченная масштабируемость . Частое отслеживание кэша вызывает гонку с доступом со стороны процессора, таким образом, это может увеличить время доступа к кэшу и энергопотребление. Каждый из запросов должен быть передан всем узлам в системе. Это означает, что размер (физической или логической) шины и предоставляемая ею пропускная способность должны расти по мере увеличения системы. [2] Поскольку отслеживание шины плохо масштабируется, более крупные системы когерентного кэша NUMA (ccNUMA) имеют тенденцию использовать протоколы когерентности на основе каталогов .
Когда транзакция шины происходит в определенном блоке кэша, все шпионы должны шпионить за транзакцией шины. Затем шпионы ищут свой соответствующий тег кэша , чтобы проверить, есть ли у него тот же блок кэша. В большинстве случаев кэши не имеют блока кэша, поскольку хорошо оптимизированная параллельная программа не делит много данных между потоками. Таким образом, поиск тега кэша шпионом обычно является ненужной работой для кэша, у которого нет блока кэша. Но поиск тега нарушает доступ к кэшу процессором и влечет за собой дополнительное потребление энергии.
Один из способов уменьшить ненужное отслеживание — использовать фильтр отслеживания. Фильтр отслеживания определяет, нужно ли отслеживателю проверять свой тег кэша или нет. Фильтр отслеживания — это структура на основе каталогов, которая отслеживает весь когерентный трафик, чтобы отслеживать состояния когерентности блоков кэша. Это означает, что фильтр отслеживания знает кэши, в которых есть копия блока кэша. Таким образом, он может предотвратить ненужное отслеживание кэшами, в которых нет копии блока кэша. Существует три типа фильтров в зависимости от расположения фильтров отслеживания. Один из них — исходный фильтр, который находится на стороне кэша и выполняет фильтрацию до того, как трафик когерентности достигнет общей шины. Другой — фильтр назначения, который находится в кэшах приемника и предотвращает ненужные поиски тега кэша в ядре приемника, но этот тип фильтрации не может предотвратить первоначальное сообщение о когерентности от источника. Наконец, внутрисетевые фильтры динамически отсекают трафик когерентности внутри общей шины. [7] Фильтр snoop также классифицируется как инклюзивный и эксклюзивный. Инклюзивный фильтр snoop отслеживает наличие блоков кэша в кэшах. Однако эксклюзивный фильтр snoop отслеживает отсутствие блоков кэша в кэшах. Другими словами, попадание в инклюзивный фильтр snoop означает, что соответствующий блок кэша удерживается кэшами. С другой стороны, попадание в эксклюзивный фильтр snoop означает, что ни один кэш не имеет запрошенного блока кэша. [8]
{{cite book}}
: CS1 maint: location missing publisher (link)