2010-10-22 3 views
11

Читаю Барьеры памяти Пол Э. McKenney http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf все объяснено в больших деталях, и когда я вижу, что все ясно, я встречаю одно предложение, которое сводит на нет все и заставить меня думать что я ничего не понял. Позвольте мне показать примерMemory Заборы - Нужна помощь, чтобы понять

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 
} 

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

Многие архитектуры CPU поэтому обеспечивают более слабую ПАМЯТЬ надбарьерного инструкции, которые делают только один или другой из этих двух. Грубо говоря, «прочитанный барьер памяти» отмечает только недействительной очереди, а «память записи барьер» отмечает только буфер хранилища. в то время как полноценный барьер памяти делает оба.

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

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

так

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

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

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

Большое спасибо за внимание.

ответ

10

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

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

read 
read 
read 
READ BARRIER 
read 
read 
read 

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

Какие нагрузки в bar() должны быть выполнены до начала загрузки a (№4)?

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

+0

Спасибо за ваш ответ, но если мы посмотрим на пример пункта 4.3 в статье, мы увидим пример, когда на самом деле все чтения b (# 3) предшествуют чтению без барьера памяти и утверждение все еще не выполняется, потому что CPU 1 выполняет assert (a == 1), и, поскольку старое значение «a» все еще находится в кеше CPU 1, это утверждение не выполняется. – confucius

+0

В фиксированном коде (с барьером чтения) CPU 1 выполняет assert (a == 1), а с строка кэша, содержащая «a», больше не находится в кеш ЦП 1 (поскольку барьер чтения вынужден лишить строку кэша), он передает сообщение «читать». – confucius

+0

Значит, это не просто заказ, не так ли? Я не понимаю, как это можно объяснить, просто сказав, что это заставляет упорядочить. Я думаю, что есть кое-что, что я не понимаю, некоторые фундаментальные детали, которые не позволяют мне присоединиться ко всей информации, которую я имею, и получить окончательную картину. – confucius

Смежные вопросы