Введение

Протокол обеспечения когерентности кэша включает в себя состояние Exclusive как расширение протокола MSI. Протокол MESI является протоколом когерентности кэша, основанным на инвалидации (invalidate), и является одним из наиболее распространенных протоколов, поддерживающих кэши с обратной записью. Он также известен как протокол Иллинойса, поскольку был разработан в Университете Иллинойса в Урбане-Шампейне. Кэши с обратной записью могут значительно экономить пропускную способность, которая обычно расходуется в кэшах с прямой записью. В кэшах с обратной записью всегда присутствует состояние "грязный" (dirty), указывающее на то, что данные в кэше отличаются от данных в основной памяти. Протокол Иллинойса требует передачи данных между кэшами при промахе, если блок находится в другом кэше. Этот протокол снижает количество обращений к основной памяти по сравнению с протоколом MSI, что значительно повышает производительность.

Готовы к владению

Read For Ownership (RFO) — это операция в протоколах обеспечения когерентности кэша, объединяющая чтение и широковещательную инвалидацию. Операция инициируется процессором, пытающимся записать в строку кэша, находящуюся в состояниях общего доступа (S) или недействительного (I) протокола MESI. Операция приводит к тому, что все остальные кэши устанавливают состояние этой строки в I. Транзакция чтения для получения права собственности — это операция чтения с намерением записи по этому адресу памяти. Следовательно, эта операция является эксклюзивной. Она извлекает данные в кэш и инвалидирует все остальные кэши процессоров, содержащие эту строку памяти. В таблицах выше это обозначено как "BusRdX".

Препятствия для памяти

MESI в своей наивной и прямолинейной реализации проявляет две конкретные проблемы с производительностью. Во-первых, при записи в недействительную линию кэша возникает значительная задержка, пока эта линия не будет получена от других процессоров. Во-вторых, перевод линий кэша в недействительное состояние требует много времени. Для уменьшения этих задержек процессоры используют буферы записи и очереди аннулирования.

Буфер хранения

Буфер записи используется при записи в недействительную строку кэша. Поскольку запись всё равно будет выполнена, процессор выдаёт сообщение об аннулировании чтения (в результате чего аннулируется рассматриваемая строка кэша, а также все строки кэша других процессоров, содержащие этот адрес памяти), а затем помещает запись в буфер записи для выполнения, когда строка кэша наконец поступит в кэш. Прямым следствием существования буфера записи является то, что при фиксации записи процессором, эта запись не записывается в кэш немедленно. Поэтому, когда процессору необходимо прочитать строку кэша, он сначала просматривает свой собственный буфер записи на предмет наличия этой же строки, поскольку существует вероятность, что та же строка была записана этим же процессором ранее, но ещё не записана в кэш (предыдущая запись всё ещё ожидает в буфере записи). Следует отметить, что процессор может читать свои собственные предыдущие записи из буфера записи, но другие процессоры не могут видеть эти записи, пока они не будут сброшены в кэш. Процессор не может просматривать буферы записи других процессоров.

Отрегулировать очереди

Что касается сообщений об аннулировании, процессоры реализуют очереди аннулирования, в которых входящие запросы на аннулирование немедленно подтверждаются, но не выполняются сразу. Вместо этого сообщения об аннулировании помещаются в очередь аннулирования, а их обработка происходит как можно скорее (но не обязательно мгновенно). Следовательно, процессор может не знать о том, что строка кэша в его кэше фактически недействительна, поскольку очередь аннулирования содержит аннулирования, которые были получены, но еще не применены. Важно отметить, что, в отличие от буфера записи, процессор не может просматривать очередь аннулирования, так как процессор и очередь аннулирования физически расположены по разные стороны кэша. В результате требуются барьеры памяти. Барьер записи очищает буфер записи, гарантируя, что все записи были применены к кэшу данного процессора. Барьер чтения очищает очередь аннулирования, тем самым обеспечивая видимость всех записей, сделанных другими процессорами, для процессора, выполняющего очистку. Кроме того, блоки управления памятью не просматривают буфер записи, что вызывает аналогичные проблемы. Этот эффект наблюдается даже в однопоточных процессорах.

Преимущества MESI по сравнению с MSI

Наиболее заметное различие между протоколами MESI и MSI заключается в дополнительном "исключительном" состоянии, присутствующем в MESI. Это состояние было добавлено из-за его многочисленных преимуществ. Когда процессору необходимо прочитать блок, которого нет ни в одном из других кэшей, а затем записать в него, в случае MSI потребуется две шинных транзакции. Сначала отправляется запрос BusRdX для чтения блока, а затем запрос BusUpgr перед записью. Запрос BusRdX в этом сценарии избыточен, поскольку ни один из других кэшей не содержит этот блок, но кэш не имеет возможности это узнать. Таким образом, протокол MESI решает эту проблему, добавляя состояние Exclusive, что позволяет избежать одной шинной транзакции. Это особенно важно при работе с последовательными приложениями. Поскольку над фрагментом данных работает только один процессор, все обращения к нему будут эксклюзивными. В этом случае MSI работает значительно медленнее из-за дополнительных сообщений в шине. Даже при использовании высокопараллельных приложений с минимальным обменом данными, MESI работает быстрее. Добавление состояния Exclusive не требует дополнительных затрат, поскольку 3 состояния и 4 состояния можно представить двумя битами.

Недостаток MESI

В случае, если различные кэши непрерывно выполняют операции чтения и записи к одному и тому же блоку, данные необходимо каждый раз сбрасывать в шину. Таким образом, основная память будет получать эти данные при каждом сбросе и оставаться в чистом состоянии. Однако это не является обязательным требованием, а лишь дополнительными накладными расходами, связанными с использованием протокола MESI. Эта проблема была решена протоколом MOESI. В состоянии S (Shared State) несколько контроллеров, отслеживающих шину, могут ответить сообщением FlushOpt с одинаковыми данными (см. пример выше). Состояние F в протоколе MESIF устраняет эту избыточность.