StoreLoad Память Барьер
Я не могу понять определение барьера StoreLoad в Cooperbook JSR-133.
store1; StoreLoad; LOAd2
Барьеры StoreLoad защищают от последующей загрузки неправильно, используя значение данных Store1, а не от более недавнего хранилища в то же место, выполненное другим процессором.
Означает ли это, что без барьера StoreLoad процессор может создать Store1 в свой буфер записи и загрузить это сохраненное значение из своего буфера записи, даже если какой-то другой процессор сделал запись в ту же ячейку памяти и сбрасывается в кэш между Store1 и LOAd1?
1 ответ
Да, это возможно, в зависимости от модели заказа памяти.
Буфер записи обычно выполняется перед отправкой, что означает, что хранилища внутри еще не доступны внешнему миру. Однако для повышения производительности большинство микроархитектур позволяют выполнять младшие загрузки в одном и том же потоке, и, если адрес совпадает с адресом хранилища, можно выполнить пересылку данных, чтобы программа продолжалась максимально быстро, при этом нагрузка выглядела так, как будто это было сделано после магазина.
Это прекрасно работает для внутрипоточной согласованности, но когда внешние процессоры обращаются к одному и тому же адресу и, возможно, изменяют данные, загрузка может слишком поздно это увидеть (хотя на многих процессорах это все равно может быть перехвачено, если загрузка не произошла). комплектации пока нет, и машина сама себя починит).
Я не совсем уверен, что цитата предназначена для объяснения, но я думаю, что это может быть лучше продемонстрировано с помощью этого сценария:
CPU0: CPU1:
store [x]<--1
store [x]<--2
store [y]<--2
load r1<--[x]
load r2<--[y]
Возможный результат (в теории) без барьера r1 == 1, r2 == 2
Это означает, что оба хранилища по CPU1 уже были выполнены (так как мы читаем 2
от [y]
), но как-то старая ценность [x]
выжил (потому что его переправили).
Мне не очень нравится этот пример, во-первых, потому что, как я уже сказал, большинство процессоров должны успешно отыскивать старое значение этой нагрузки даже после того, как она была выполнена. Во-вторых, это слишком сложно, потому что они настаивали на том, чтобы:
StoreLoad строго необходим только для отделения магазинов от последующих загрузок того же места (мест), которые были сохранены до барьера
Это неправильно, барьер также необходим, когда адреса различаются, что можно увидеть в следующем (классическом) примере:
CPU0: CPU1:
store [x]<--1 store [y]<--1
load r1<--[y] load r2<--[x]
Здесь адреса разные, и все же требуется барьер, чтобы предотвратить случай, когда обе загрузки читают старые значения (хотя оба хранилища должны были быть выполнены, чтобы туда попасть), благодаря выполнению нагрузок вне порядка. Обратите внимание, что это проблема, отличная от представленной (сохранение для загрузки), но это доказывает, что цитата неверна.