Ответы:
Для повышения производительности современные процессоры часто выполняют инструкции не по порядку, чтобы максимально использовать доступную микросхему (включая чтение / запись в память). Поскольку оборудование обеспечивает целостность инструкций, вы никогда не заметите этого в одном потоке выполнения. Однако для нескольких потоков или сред с энергозависимой памятью (например, ввод-вывод с отображением памяти) это может привести к непредсказуемому поведению.
Забор / барьер памяти - это класс инструкций, которые означают, что чтение / запись в память происходят в ожидаемом вами порядке. Например, «полное ограждение» означает, что все операции чтения / записи до ограждения выполняются перед операциями после ограждения.
Обратите внимание, что ограждения памяти - это аппаратная концепция. В языках более высокого уровня мы привыкли иметь дело с мьютексами и семафорами - они вполне могут быть реализованы с использованием ограждений памяти на низком уровне, и явное использование барьеров памяти не требуется. Использование барьеров памяти требует тщательного изучения архитектуры оборудования и чаще встречается в драйверах устройств, чем в коде приложения.
Переупорядочивание ЦП отличается от оптимизации компилятора, хотя артефакты могут быть похожими. Вам необходимо принять отдельные меры, чтобы компилятор не переупорядочивал ваши инструкции, если это может вызвать нежелательное поведение (например, использование ключевого слова volatile в C).
Копирую ответ на другой вопрос : какие уловки использует процессор для оптимизации кода? :
Самым важным из них будет изменение порядка доступа к памяти.
При отсутствии ограждений памяти или инструкций по сериализации процессор может изменять порядок доступа к памяти. Некоторые архитектуры процессоров имеют ограничения на то, сколько они могут переупорядочивать; Альфа известна как самая слабая (т. Е. Та, которая больше всего может изменить порядок).
Очень хорошее рассмотрение этого вопроса можно найти в документации к исходному тексту ядра Linux по адресу Documentation / memory-barriers.txt .
В большинстве случаев лучше использовать блокирующие примитивы из вашего компилятора или стандартной библиотеки; они хорошо протестированы, должны иметь все необходимые барьеры памяти и, вероятно, достаточно оптимизированы (оптимизировать блокирующие примитивы сложно; даже эксперты иногда могут ошибаться).
Alpha is known for being the weakest
, почему weakest
? Не лучше ли переупорядочить больше, чтобы в результате выполнение было намного быстрее? (Я не альфа-пользователь, но спрашиваю о влиянии very reordering
vs restricted reordering
). Итак, каковы недостатки переупорядочения партий (за исключением риска неопределенного поведения, но я предполагаю, что большинство современных процессоров должны были решить хороший переупорядочение и реализовать только определенное переупорядочение, иначе это не имело бы смысла в принятом ими решении).
По моему опыту, это относится к барьеру памяти , который представляет собой инструкцию (явную или неявную) для синхронизации доступа к памяти между несколькими потоками.
Проблема возникает в сочетании современных агрессивных компиляторов (они обладают удивительной свободой переупорядочивать инструкции, но обычно ничего не знают о ваших потоках) и современных многоядерных процессоров.
Хорошим введением к проблеме является « Декларация « Двойная проверка блокировки нарушена » ». Для многих это был тревожный сигнал о существовании драконов.
Неявные барьеры полной памяти обычно включаются в подпрограммы синхронизации потоков платформы, которые покрывают ее ядро. Однако для программирования без блокировок и реализации настраиваемых облегченных шаблонов синхронизации часто требуется только барьер или даже только односторонний барьер.
Барьер памяти, также известный как мембрана или забор памяти, представляет собой класс инструкций, которые заставляют центральный процессор (ЦП) применять ограничение порядка операций с памятью, выполняемых до и после инструкции барьера.
ЦП применяют оптимизацию производительности, которая может привести к неупорядоченному выполнению, включая загрузку памяти и операции сохранения. Переупорядочение операций с памятью обычно остается незамеченным в рамках одного потока выполнения, но вызывает непредсказуемое поведение в параллельных программах и драйверах устройств, если не контролируется тщательно. Точная природа ограничения порядка зависит от оборудования и определяется архитектурной моделью памяти. Некоторые архитектуры предоставляют несколько препятствий для наложения различных ограничений порядка.
Барьеры памяти обычно используются при реализации низкоуровневого машинного кода, который работает с памятью, совместно используемой несколькими устройствами. Такой код включает примитивы синхронизации и незаблокированные структуры данных в многопроцессорных системах, а также драйверы устройств, которые обмениваются данными с компьютерным оборудованием.