В системе с двумя ядрами и кэшем с протоколом MESI дано начальное состояние: оба кэша имеют строку A в состоянии Shared, память содержит A=0; затем процессор 1 выполняет запись A=1, процессор 2 выполняет чтение A; опишите все переходы состояний MESI, необходимые шины-сообщения, возможные гонки и как разные реализации протокола (snooping vs directory) повлияют на задержку и пропускную способность

23 Окт в 12:44
4 +1
0
Ответы
1
Кратко и по делу — по шагам, с нужными переходами MESI, шинами/сообщениями, возможными гонками и влиянием snooping vs directory.
Исходное: оба кэша имеют строку A в состоянии Shared, память содержит A=0.\;A=0.A=0.
1) Процессор 1 записывает A=1.\;A=1.A=1. - Состояние в C1: было SSS и это write-hit в SSS. Для записи нужен эксклюзив/модифицированный экземпляр. Типичный механизм:
- C1 генерирует транзакцию "upgrade"/"Read-for-Ownership" (на шине: BusUpgr или BusRdX / RFO) для строки A.
- C2, видя BusUpgr, снапит и инвалидирует свою копию: S→IS \to ISI. (C2 присылает ack/inv-ack по шине.)
- После получения подтверждений C1 переходит S→MS \to MSM и выполняет запись в кэш: теперь в C1 A=1\;A=1A=1 в состоянии MMM. Память пока содержит A=0\;A=0A=0 (запись в память отложена до writeback).
- Необходимые шина‑сообщения: BusUpgr/BusRdX (request for ownership), invalidate/ack от других кешей; (в реализации без BusUpgr вместо него может быть BusRdX, который дополнительно перемещает данные, но в нашем случае данные уже есть — BusUpgr быстрее).
2) Затем процессор 2 читает A.
- Состояние в C2: стало III (после инвалидации). Чтение — промах.
- C2 генерирует BusRd (read miss).
- C1, имея строку в MMM, снупит BusRd и делает "flush"/"intervention": поставляет актуальные данные на шину (cache‑to‑cache transfer) и обычно делает writeback в память или передаёт данные напрямую; при этом C1 переходит M→SM \to SMS.
- C2 получает данные A=1\;A=1A=1 и переходит I→SI \to SIS.
- Итог: оба кэша SSS со значением A=1\;A=1A=1; память либо обновлена в результате flush (т.е. A=1\;A=1A=1), либо оставлена до следующего writeback, но видимые кэшу данные корректны.
- Необходимые шина‑сообщения: BusRd, cache‑to‑cache data transfer или owner writeback, acks.
Возможные гонки (если операции перекрываются по времени)
- Сценарий: P1 делает BusUpgr и одновременно P2 делает BusRd. Порядок разрешается арбитром шины (или директором).
- Если BusUpgr выигрывает (обрабатывается первым): C2 будет инвалидирован до чтения, затем P1 запишет A=1\;A=1A=1, и последующий BusRd от P2 принесёт A=1\;A=1A=1.
- Если BusRd выигрывает первым: P2 может получить старое значение A=0\;A=0A=0 (из памяти или из кэша C1/C2, так как перед записью C1 ещё в состоянии SSS), затем BusUpgr от P1 исполнится и обновит строку до A=1\;A=1A=1. В результате P2 видел старое значение — это корректно, так как глобальный порядок операций определяется порядком транзакций на шине.
- Итого: race приводит к разным наблюдаемым порядкам чтения/записи в зависимости от глобального упорядочения шина; протокол поддерживает согласованность, но не атомарность операций без дополнительных синхронизирующих механизмов.
Чем отличаются реализации snooping и directory (влияние на задержку и пропускную способность)
- Snooping (шина‑базированное):
- Все транзакции широковещательно объявляются на общей шине; все кэши снупят одновременно.
- Задержка: на малом числе ядер (2 ядра) очень низкая — broadcast быстрый, часто возможен cache‑to‑cache transfer без обращения к памяти.
- Пропускная способность: ограничена одной транзакцией на шину одновременно (сильная точка узкого места). При росте числа ядер шина перегружается, падает пропускная способность.
- Поведение гонок: разрешается арбитром шины; порядок транзакций глобален.
- Directory (директорская):
- Есть централизованная таблица (directory), хранящая список шареров/владельца для строки A.
- Операция P1 write: P1 посылает request-for-exclusive к директору; дир. отправляет invalidates only to указанных шареров (п/п-респонсы), после чего даёт грант P1. Т.е. вместо широковещательного BusUpgr — точечные сообщения.
- Операция P2 read: P2 посылает Read-request к директору; директор перенаправляет request владельцу (или из памяти), владелец шлёт данные владельцу/директору/запрашивающему.
- Задержка: обычно чуть выше в простых системах (доп. hop к директору и от него), особенно если director находится в удалённом узле; но для больших систем latency/широковещание уменьшается, поскольку не нужно бродкастить на всех.
- Пропускная способность: лучше масштабируется — можно параллелить операции по разным строкам и избегать глобальной шины‑узкого места.
- Поведение гонок: директор сериализует запросы для данной строки, что упрощает разрешение гонок (централизованный порядок).
Краткие выводы
- Конкретная последовательность в нашем случае (без перекрытия): C1 S→BusUpgrS \xrightarrow{\text{BusUpgr}}SBusUpgr MMM (запись A=1\;A=1A=1); затем C2 miss: BusRd → C1 M→SM \to SMS, C2 I→SI \to SIS, обе копии A=1\;A=1A=1.
- Гонки зависят от порядка обработки BusUpgr vs BusRd; возможен сценарий, где читатель получает старое A=0\;A=0A=0 если его BusRd обработан раньше.
- Snooping быстрее для 2‑ядерной системы (меньше хопов), но имеет ограниченную пропускную способность при росте числа ядер; directory чуть более дорог в задержке (хопы), но масштабируется лучше и уменьшает широковещательный трафик.
23 Окт в 13:02
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир