С ++ 11 atomic автоматически решает многоядерную гонку на переменные чтения-записи? - PullRequest
0 голосов
/ 10 ноября 2018

Я знаю, что atomic будет применять блокировку к переменной типа "T", когда несколько потоков читают и записывают переменную, убедившись, что только один из них выполняет R / W.

Но на компьютере с многоядерным процессором потоки могут работать на разных ядрах, и разные ядра будут иметь разный L1-кеш, L2-кеш, а совместно использовать L3-кеш. Мы знаем, что иногда компилятор C ++ оптимизирует переменную, которая будет храниться в регистре, так что, если переменная не хранится в памяти, не происходит синхронизация памяти между различными ядрами-кешами в переменной.

Так что мой вопрос / беспокойство заключается в том, что если атомная переменная оптимизирована компилятором как некоторая регистровая переменная, то она не сохраняется в памяти, когда одно ядро ​​записывает свое значение, другое ядро ​​может считывать устаревшее значение, верно? Есть ли гарантия непротиворечивости этих данных?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Atomic не «решает» вещи так, как вы смутно описываете.Он предоставляет определенные весьма специфические гарантии для обеспечения согласованности памяти в зависимости от порядка.

Различные компиляторы реализуют эти гарантии по-разному на разных платформах.

На x86 / 64 блокировки не используются для атомарных целых чисел иуказатели до разумного размера.А аппаратное обеспечение обеспечивает более строгие гарантии, чем требует стандарт, что делает некоторые из более эзотерических вариантов эквивалентными полной согласованности.

Я не смогу полностью ответить на ваш вопрос, но могу указать вам верное направление;тема, которую вам нужно изучить, - это «модель памяти C ++».

При этом существует атомарность, чтобы избежать точной проблемы, которую вы описываете.Если вы запрашиваете полную последовательность порядка памяти, и поток A изменяет X, то Y, никакой другой поток не может видеть измененный Y, кроме X. То, как обеспечивается эта гарантия, не определено стандартом C ++;аннулирование строки кэша, использование специальных инструкций для доступа, запрет определенных оптимизаций на основе регистра компилятором и т. д. - все это то, что делают компиляторы.

Обратите внимание, что модель памяти C ++ была уточнена, исправлена ​​и исправлена ​​дляC ++ 17, чтобы описать поведение новых параллельных алгоритмов и обеспечить их эффективную реализацию на оборудовании GPU (среди прочих мест) с правильными флагами, что, в свою очередь, повлияло на гарантии, предоставляемые новым оборудованием GPU.Так что люди, говорящие о моделях памяти, могут быть взволнованы и говорить о более современных проблемах, чем ваши в основном проблемы C ++ 11.

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

0 голосов
/ 10 ноября 2018

Возможно, вы ищете это:

[intro.progress] / 18 Реализация должна обеспечивать, чтобы последнее значение (в порядке изменения), назначенное атомарной операцией или операцией синхронизации, стало видимым для всех других потоков за конечный период времени.

...