Достаточно ли протокола MESI или все еще требуются барьеры памяти? (Процессоры Intel)

Я нашел документ Intel, в котором говорится, что барьеры памяти необходимы, когда строка (не std::string, но используются инструкции сборочной строки), чтобы предотвратить их повторное упорядочение процессором.

Однако необходимы ли барьеры памяти, когда два потока (на двух разных ядрах) обращаются к одной и той же памяти? Я имел в виду сценарий, когда один из процессоров, который не "владеет" строкой кэша, записывает данные в эту память, а ядро ​​записывает данные в свой буфер хранения (в отличие от своего кэша). Для сброса значения из буфера хранилища в кеш требуется барьер памяти, чтобы другое ядро ​​могло получить это значение?

Я не уверен, обрабатывает ли это на Intel протокол MESI?

(то, что я попытался (плохо) объяснить выше, лучше описано в статье ниже, страницы 6-12):

http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf

Приведенный выше документ носит очень общий характер, и я не уверен, что процессоры Intel практически справляются с этой проблемой.

2 ответа

Протоколы MESI применяются к кешам, буферизация хранилища по существу является предварительным кешированием, то есть это хранилище, которое еще не было "выпущено" для внешнего мира, и его точка синхронизации еще не была определена.

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

Это само по себе не дает вам гарантии на порядок записи и чтения из нескольких ядер, для этого вам нужно управлять своим кодом, используя дополнительные конструкции, которые предоставляет ISA, такие как блокировки, ограничения и использование правил упорядочения памяти.

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

Однако, если 2 ядра записывают в одну и ту же строку одновременно, протокол MESI гарантирует, что эти записи будут иметь некоторый порядок, а не тот, который вам нужен. Хуже того - если каждое ядро ​​записывает несколько строк, и вы хотите атомарности вокруг этих записей, MESI не гарантирует этого. Вам нужно будет активно добавить мьютекс или некоторый барьер, чтобы заставить HW выполнять запись так, как вы хотите.

Я думаю, что вы говорите о ERMSB (быстрые строки) в Intel IvB и позже делая rep movs используйте слабо упорядоченные записи.

Мой вывод из документации Intel заключается в том, что вам все еще не нужно SFENCE заказать эти магазины относительно других магазинов, и, конечно, вы не можете запустить SFENCE в середине rep movsb, Посмотрите этот ответ, чтобы узнать больше о барьерах памяти на x86.

AFAICT, все, что вам нужно сделать, это избегать использования того же rep movs написать буфер и флаг, который читатели проверят, чтобы увидеть, готов ли буфер. Читатель мог видеть флаг до того, как все хранилища в буфере будут видны ему. Это единственный способ, которым новая функция ERMSB влияет на корректность, для программ, которые уже были правильными (то есть не зависели от случайных ошибок). Это положительно сказывается на производительности memcpy / memset.

Другие вопросы по тегам