2013-11-21 4 views
1

Существуют ли типы, которые я могу прочитать или изменить или сравнить по-своему по умолчанию? Или я должен использовать атомарные операции явно для ВСЕХ типов для ВСЕХ операций?Атомные инструкции и атомный тип

+0

@Damon Я думаю, вы должны это ответить – Slava

+0

'std :: atomic ' - это тип, который вы всегда читаете и изменяете атомарно (точнее, преобразование в 'T' автоматически выполняет атомную нагрузку и назначение из 'T' выполняет атомный магазин). Я не уверен, что вы подразумеваете под «сравнить атомарно». –

ответ

1

Да, вы должны всегда использовать атомные типы или атомные операции, если вам нужна атомарность. Ничего другого.

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

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

Атомные операции, следовательно, имеют связанную с ними «модель памяти», которая позволяет вам предоставлять дополнительную информацию о том, что происходит, - перед гарантиями, которые необходимы между потоками и между связанными или несвязанными данными. См. GCC Wiki для хорошего описания каждого режима.
По умолчанию атомные операции выбирают последовательно последовательную модель, которая является самым безопасным режимом с самыми строгими ограничениями. Вы можете выбрать другую модель, если знаете, что вам не нужны определенные гарантии, которые могут (или не могут, в зависимости от архитектуры) привести к созданию более совершенного кода.
Приятная вещь с моделями памяти заключается в том, что они абстрагируют детали реализации, архитектурные особенности и компилятор voodoo в форме, которая описывает ваши алгоритмические требования и гарантирует выполнение этих требований.

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

Смежные вопросы