Что на самом деле делает Memory_order_consume?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Что на самом деле делает Memory_order_consume?

Сообщение Anonymous »

По ссылке:
В чем разница между загрузкой/сохранением расслабленной атомарной и обычной переменной?
Меня глубоко впечатлил этот ответ:

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

Сегодня я прочитал ссылку ниже:
https://preshing.com/20140709/the-membe ... -in-cpp11/

Код: Выделить всё

atomic Guard(nullptr);
int Payload = 0;
thread1:

Код: Выделить всё

  Payload = 42;
Guard.store(&Payload, memory_order_release);
thred2:

Код: Выделить всё

g = Guard.load(memory_order_consume);
if (g != nullptr)
p = *g;
Изображение

ВОПРОС:
Я узнал, что Зависимость данных предотвращает переупорядочение связанных инструкций.
Но я думаю, что это очевидно для обеспечения правильности результатов выполнения. Не имеет значения, существует ли семантика comsume-release или нет.
Так что мне интересно, действительно ли comsume-release существует. О, может быть, он использует зависимости данных, чтобы предотвратить изменение порядка инструкций, гарантируя видимость полезной нагрузки?
Так
Это можно получить тот же правильный результат, используя Memory_order_relaxed, если я сделаю эту 1.предотвращение переупорядочения инструкций
2.обеспечение видимости неатомарной переменной полезной нагрузки
:

Код: Выделить всё

atomic Guard(nullptr);
volatile int Payload = 0;   // 1.Payload is volatile now

// 2.Payload.assign and Guard.store in order for data dependency
Payload = 42;
Guard.store(&Payload, memory_order_release);

// 3.data Dependency make w/r of g/p in order
g = Guard.load(memory_order_relaxed);
if (g != nullptr)
p = *g;      // 4. For 1,2,3 there are no reorder, and here, volatile Payload make the value of 42 is visable.
Дополнительное содержимое (благодаря ответу Sneftel):
1.Payload = 42;
Летучий make запись полезных данных в/из основной памяти, но не в/из кэша. Таким образом, 42 будет записывать в память.
2.Guard.store(&Payload, любой флаг MO можно использовать для письмо); Как вы сказали, Guard является энергонезависимым, но атомарным.

Использование атомарной переменной решает проблему - при использовании атомарности все
потоки гарантированно будут читайте последнее записанное значение, даже если
порядок памяти ослаблен.
Фактически, атомарность всегда потокобезопасна, независимо от
порядка памяти! Порядок памяти не для атомарных -> он предназначен для неатомарных
данных.

Поэтому после выполнения Guard.store, Guard.load ( с любым флагом MO, который можно использовать для чтения), можно правильно получить адрес полезной нагрузки. А затем правильно получите 42 из памяти.
Приведенный выше код:
1. Нет эффекта переупорядочения для зависимости данных.
2.нет эффекта кэширования для энергозависимой полезной нагрузки
3.нет проблем с потокобезопасностью для атомной защиты
Могу ли я получить правильное значение - 42?
Вернуться на главную вопрос

Когда вы используете семантику потребления, вы по сути пытаетесь заставить
компилятор использовать зависимости данных на всех этих семействах процессоров .
Поэтому, как правило, недостаточно просто заменить
memory_order_acquire на Memory_order_consume. Вы также должны убедиться, что
на уровне исходного кода C++ существуют цепочки зависимостей данных.

Изображение

" Вы также должны убедиться, что на уровне исходного кода C++ существуют цепочки зависимостей данных. ."
Я думаю, что цепочки зависимостей данных на уровне исходного кода C++ препятствуют естественному переупорядочению инструкций.
Итак, что на самом деле делает Memory_order_consume?
И могу ли я использовать Memory_order_relaxed для достижения того же результата, что и приведенный выше код?
Конец дополнительного контента

Подробнее здесь: https://stackoverflow.com/questions/653 ... -really-do
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»