Подтвердить что ты не робот

Запоминания памяти - нужна помощь для понимания

Я читаю "Барьеры памяти" Пауля Маккенни http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf все объясняется в подробностях, и когда я вижу, что все ясно, я встречаю одно предложение, которое затуманивает все и заставляет меня думать, что я ничего не понял. Позвольте мне показать пример

void foo(void)
{
   a = 1; #1
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   assert(a == 1); #4
}

скажем, что эти две функции работают на разных процессорах. Теперь, что может случиться, это хранить до # 1, который можно увидеть после хранения в b # 2 вторым процессором, потому что первые очереди процессоров хранятся в "a" и продолжают хранить инструкцию b. Хорошо, это прекрасно, мы добавляем забор записи в строке между # 1 и # 2, но этот код все еще может выйти из строя, потому что второй процессор может поставить в очередь сообщение invalidate, поэтому мы добавим еще один забор памяти (на этот раз читаем забор) в линия между # 4 и # 4.

void foo(void)
{
   a = 1; #1
   write_memory_barrier();
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   read_memory_barrier();
   assert(a == 1); #4
}

это принуждает второй процессор обрабатывать все сообщения в очереди (invalidate a) и читать его снова, отправляя сообщение MESI для первого процессора на # 4. ОК. Далее в статье говорится:

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

Отлично, это ясно, но после этого я вижу это

Эффект от этого заключается в том, что чтение Заказы на защиту памяти только загружаются CPU, который его выполняет, чтобы все нагрузки, предшествующие памяти чтения барьер, похоже, завершился перед загрузкой после считывания барьер памяти. Аналогично, запись память защищает только магазины, снова на CPU, который его выполняет, и снова, чтобы все магазины, предшествующие будет записываться барьер записи завершили работу перед любым магазином после барьера записи.

так

все нагрузки, предшествующие барьеру чтения памяти, будут как представляется, были выполнены до любой нагрузки, следующей за предел памяти чтения

который смешивает все, что было объяснено ранее. Что это значит? Какую нагрузку в функции "бар" нужно выполнить перед загрузкой "a" # 4? Я понимаю, что утверждение может выйти из строя без барьера памяти в этой функции только потому, что процессор может прочитать старое значение, потому что ему все еще не удалось лишить его строки кэша, где находится объект "a" .

Объяснение в деталях было бы действительно полезно, я пытаюсь понять его весь день.

Спасибо очень заблаговременно.

4b9b3361

Ответ 1

Что это значит?

Это означает, что если у вас есть:

read
read
read
READ BARRIER
read
read
read

тогда барьер чтения действует как "точка соединения", разделяющая эти чтения на две партии. Все прочитанные перед барьером чтения будут сделаны до того, как начнется чтение после того, как начнется считывание барьера.

Какие нагрузки в bar() должны завершиться до начала загрузки a (# 4)?

Все чтения b (# 3) вынуждены предшествовать чтению a (# 4). Это означает, что a не читается до тех пор, пока b больше не будет 0. Поскольку foo() использует барьер записи, чтобы гарантировать, что a уже был изменен на 1 (# 1) к тому времени, когда b изменяется (# 2). Таким образом, два барьера работают вместе, чтобы гарантировать, что утверждение assert всегда будет успешным.