Как std :: atomic обеспечивает атомарность - PullRequest
0 голосов
/ 20 января 2019

Если у меня есть код a = a + 1, теперь я понимаю, что для выполнения этого требуется несколько операций на уровне ЦП, но как определение a как std::atomic<int> делает эти множественные транзакции атомарными?

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

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

Ответы [ 2 ]

0 голосов
/ 20 января 2019

[B] но как определение as как std :: atomic делает эти множественные транзакции атомарными?

Это не делает атомарные «множественные транзакции» в произвольном выражении (например, это не поможет в вашем a = a + 1 примере).Скорее, вам нужно использовать операцию типа a++, которая гарантированно будет атомарной.В этом случае способ его реализации зависит от компилятора и аппаратного обеспечения, но наиболее распространенными являются следующие стратегии:

  • Используется одна инструкция атомарная операция , которая может автоматически увеличиватьзначение в памяти.На x86 это будет что-то вроде инструкция lock add.
  • Некоторый тип сравнения и обмена (CAS) или с нагрузкойЦепочка условного хранения (LL-SC) используется для многократной попытки сделать приращение атомарным способом.Вы можете увидеть LL-SC в действии на MIPS64.
  • Наконец, на платформах, которые не поддерживают такие операции, или где тип данных несовместим с этими инструкциями, можно получить блокировкуисключить любой параллельный доступ при выполнении операции с обычными неатомарными инструкциями.Большинству основных платформ не нужно прибегать к этому для атомарных типов, но вы все еще можете увидеть пример здесь на старом компиляторе ARM.

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

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

Компилятор не всегда генерирует их, потому что они дорого стоят на аппаратном уровне.Например, обычное (неатомарное) сложение обычно занимает 1 цикл или меньше 2 на большинстве современных процессоров 1 , в то время как атомарное сложение может занимать от 15 до 100 циклов.Подходы, использующие CAS или LL-SC, как правило, еще медленнее и требуют повторных циклов, увеличивая размер двоичного файла.


1 Возможно, до нескольких циклов на некоторых микроконтроллерахклассовые процессоры - но там атомарные операции часто менее актуальны, так как может не быть нескольких ядер.

2 Зависит от того, как вы его измеряете - сложение обычно занимает один цикл до завершения (задержка), но вы часто можете выполнить более одного независимого дополнения в одном цикле.Например, современные процессоры Intel могут выполнять четыре за один цикл.

0 голосов
/ 20 января 2019

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

Существует функция (C ++ 17), которая сообщает вам, всегда ли атомарный тип свободен от блокировки: is_always_lock_free. Имейте в виду, что если эта функция возвращает false, по крайней мере, некоторые операции не свободны от блокировки (не обязательно все они). Эти операции без блокировок обычно обходятся дороже, чем атомарные (сами по себе дороже, чем традиционные операции).

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

Так что он не всегда может создать такой код из 1 инструкции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...