Протокол MESI делает тайники памяти невидимыми. Это означает, что многопоточные программы не должны беспокоиться о том, что ядро считывает устаревшие данные из них или два ядра, записывая в разные части строки кэша, и получая половину одной записи и половину другой, отправленной в основную память.
Однако это не помогает при выполнении операций чтения-изменения-записи, таких как приращение, сравнение и свопинг и т. Д. Протокол MESI не останавливает два ядра от каждого чтения одного и того же блока памяти, каждый из которых добавляет к нему один, а затем каждый записывает одно и то же значение обратно, поворачивая два шага в один.
На современных процессорах префикс LOCK блокирует линию кэша так, что операция чтения-изменения-записи логически атомарна. Они упрощены, но, надеюсь, они дадут вам эту идею.
разблокирована шаг:
- Приобретать строки кэша, разделяемых прекрасно. Прочитайте значение.
- Добавьте один к считываемому значению.
- Приобретать кеш-строку эксклюзивно (если она еще не E или M) и заблокировать ее.
- Запишите новое значение в строку кэша.
- Измените строку кэша, чтобы изменить и разблокировать ее.
Locked прибавка:
- Приобретать строки кэша эксклюзивные (если он еще не E или M) и зафиксировать его.
- Прочитать стоимость.
- Добавьте один к нему.
- Запишите новое значение в строку кэша.
- Измените строку кэша, чтобы изменить и разблокировать ее.
Обратите внимание на разницу? В разблокированном приращении строка кэша блокируется только во время операции записи в память, как и все записи. В заблокированном приращении строка кэша сохраняется по всей команде, полностью от операции чтения до операции записи и включающей в себя сам приращение.
Кроме того, некоторые процессоры имеют вещи, отличные от кэшей памяти, которые могут повлиять на видимость памяти. Например, у некоторых ЦП есть считыватель prefetcher или размещенный буфер записи, который может привести к тому, что операции с памятью будут выполняться не в порядке. Там, где это необходимо, префикс LOCK (или эквивалентная функциональность на других ЦП) также будет выполнять все, что необходимо для управления проблемами порядка работы с памятью.
Учитывайте разницу между заблокированным и разблокированным приращением: если два ядра одновременно увеличивают значение 0 в памяти, они оба решают записать 1 в память. Когерентность кеша не предотвращает потерю одного из обновлений. –
@ KerrekSB извините, я не совсем понял, что вы имели в виду. Не будет ли кэширование когерентности гарантировать, чтобы только один из ядер владел кэшиной? Поэтому, если второе ядро перешло к изменению кешины, в то время как первое увеличивалось, MESI предотвратил бы запись до тех пор, пока первое ядро не завершило приращение? – user997112
Инкремент - это не атомная операция. Сначала оба ядра считывают одно и то же значение (0) с чистой строки кэша. Затем они оба решают вычислить новое значение (1). Затем они оба записывают значение обратно. На этом этапе записи когерентность кэша не помогает, потому что запись в память не сразу влияет на согласованность (только чтение * с загрязненных страниц). –