Атомный декремент дороже, чем инкремент?

В его Блог Херб Саттер пишет

[…] так как увеличение счетчика ссылок умного указателя
обычно можно оптимизировать так же, как обычный прирост
в оптимизированном shared_ptr реализация — просто обычная инструкция приращения,
и никаких заборов, в сгенерированном коде.

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

Текст о реализации shared_ptr и я не уверен, относится ли его замечание только к этому или вообще имеет место. Из его формулировки я понимаю, что это в общем-то.

Но когда я думаю об этом, я могу думать только о «более дорогом декременте», когда if(counter==0) сразу следует — что, вероятно, имеет место с shared_ptr,

Поэтому мне интересно, если атомное операция ++counter обычно) всегда быстрее чем --counter, или просто потому что Это использовано if(--counter==0)... с shared_ptr?

18

Решение

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

Я не знаю ни одной архитектуры, где --counter (или же counter--при условии, что мы говорим о простых типах данных, таких как int, char и т. д.), медленнее, чем ++counter или же counter++,

11

Другие решения

Он обсуждает это более подробно где-то, я думаю, в его атомное<> оружие презентация. По сути, все дело в том, где в случае использования shared_ptr нужны ограждения памяти, а не в каких-либо внутренних свойствах атомарных приращений или приращений.

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

16

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

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

9
По вопросам рекламы [email protected]