Являются ли неделимые операции еще неделимыми в многопроцессорных и многоядерных системах? - PullRequest
4 голосов
/ 05 марта 2010

Согласно заголовку, а также ограничения и ошибки.

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

Очевидно, это можно сделать, если вы достаточно усердно работаете на любом процессореопределенные байты и т. д.), но не так, чтобы можно было ожидать, что операция записи будет неделимой.

Я серьезно сомневаюсь, что многоядерный процессор может гарантировать, что другие ядра могут гарантировать согласованность всех до или всех-после просмотра письменного указателя в этой ситуации выравнивания-пересечения-записи-границы страницы.

Я прав?И есть ли подобные ошибки, о которых я не думал?

Ответы [ 5 ]

2 голосов
/ 05 марта 2010

Само понятие единой памяти, видимой для всех потоков, перестает работать с несколькими ядрами, имеющими отдельные кэши. вопросы StackOverflow о барьерах памяти могут представлять интерес; скажем, этот .

Я думаю, что пример, иллюстрирующий проблему с моделью «с одной памятью»: Первоначально х = у = 0.

Тема 1:

X = x;
y = 1;

Тема 2:

Y = y;
x = 1;

Конечно, есть состояние гонки. Вторая проблема, помимо очевидного состояния гонки, заключается в том, что одним из возможных результатов является X = 1, Y = 1. Даже без оптимизации компилятора (даже если вы пишете два вышеупомянутых потока в сборке).

1 голос
/ 07 марта 2010

Тогда на x86 ответ «да», если операции ассемблера предшествовал инструкции блокировки, тогда процессор выдает аппаратный сигнал, который гарантирует, что следующая инструкция является атомарной (в некоторых процессорах кэши координируют, чтобы гарантировать, что операция атомарна) ,

Создание атомарных операций - это то, что компиляторы не делают, в многопроцессорных системах атомарные операции на языке ассемблера очень дороги и обычно используются для реализации примитивов блокировки, предлагаемых библиотекой OS / C.

Никакие чисто языковые операции с памятью не должны рассматриваться как атомарные. Если у вас есть несколько потоков, записывающих в одну и ту же общую память, вам нужно использовать механизм мьютекса / блокировки, чтобы избежать гонок.

1 голос
/ 07 марта 2010

Может быть, я неправильно понял пример, но проблема "не выровненный указатель" такой же, как на одноядерном исполнении. Если данные могут быть частично записывается в память, тогда разные потоки могут видеть частичные обновления (если нет подходящей блокировки) на любой машине с preemtive многозадачность (даже в однопроцессорной системе).

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

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

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

[Редактировать] Дополнение к комментарию ниже

  1. Все, что записано в память, будет видимо всем потоки, независимо от количества ядер (в кеше система).
  2. Все, что записано в память неатомно, может оказаться частично читать несинхронизированными потоками при наличии вытеснения (даже в одноядерной системе).

Если указатель записан на невыровненный адрес в одном, атомарном напишите тогда аппаратное обеспечение согласованности кеша убедится что все Нити видят, что это завершено, или нет вообще. Если указатель написан неатомно (например, с двумя отдельными операциями записи), то любой потоки могут видеть частичное обновление даже в одноядерной системе с истинным преимуществом.

0 голосов
/ 18 мая 2011

Являются ли неделимые операции еще неделимы на многопроцессорные и многоядерные системы?

Понятие «неделимого» (или «атомарного») не имеет большого смысла в последовательной (одноядерной однопотоковой) системе. Чтобы узнать, является ли что-то неделимым или нет, вам нужен внешний наблюдатель, и этот внешний наблюдатель может быть только другим потоком, запланированным на том же ядре или на другом ядре. Неделимый означает, что ни один внешний наблюдатель не может наблюдать промежуточное состояние. Позвольте мне порекомендовать книгу «Искусство многоядерного программирования» для более глубокого понимания этих концепций.

Вероятно, вы спрашиваете, являются ли, казалось бы, неделимые операции (такие как однострочное выражение x = 3) на самом деле неделимыми. Ответ - нет, и существует хорошо известный пример: обработка двойников в Java. Двойник хранится в двух 32-битных словах, и спецификация JVM не гарантирует, что операции над двойниками являются атомарными (хотя на практике они применяются на всех основных JVM). Другой поток может наблюдать состояние, когда обновлено только одно слово из двух. Еще раз, это не имеет отношения к тому, запланированы ли два потока на одном ядре или на разных ядрах.

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

0 голосов
/ 05 марта 2010

Возможно ли для этого класса вывести «False»?

class Unsafe
{
  static bool underwearOn, trousersOn;

  static void Main( )
  {
    new Thread(Wait).Start( );    // Start up the busy waiter
    Thread.Sleep(1000);           // Give it a second to start up!

    underwearOn = true;
    trousersOn = true;
  }

  static void Wait(  )
  {
    while (!trousersOn)
        ; // Spin until trousersOn
    Console.Write(underwearOn);
  }
}

Да, на многоядерных машинах. Типы значений, такие как bools, могут храниться в машинных регистрах, а регистры заказов синхронизируются в зависимости от компьютера. underwearOn может быть синхронизировано до trousersOn.

Вы можете заблокировать назначения и цикл while, но это ухудшит производительность. Лучшее решение - объявить переменные bool volatile. Такие переменные не хранятся в регистрах.

Edit:

Это упрощенный пример из презентации, доступной по адресу Threading Complete .

...