原子衰减比增量更贵吗?

tow*_*owi 18 c++ performance atomic reference-counting memory-fences

在他的Blog Herb Sutter写道

[...]因为增加智能指针引用计数 通常可以优化为与优化shared_ptr实现中的普通增量相同- 在生成的代码中只是普通的增量指令,而不是围栏.

然而,减量必须是原子减量或等效物,它产生特殊的处理器存储器指令,这些指令本身更昂贵,并且最重要的是在优化周围代码时引起存储器栅栏限制.

该文是关于执行的shared_ptr,我不确定他的评论是否只适用于此或通常是这样.从他的表述我收集它一般.

但是当我想到它时,我只能想到"更加昂贵的减量",当if(counter==0)紧接着 - 这可能就是这种情况shared_ptr.

因此,我想知道原子操作++counter是否(通常)总是快--counter,或者只是因为if(--counter==0)...shared_ptr?一起使用?

mat*_*ort 16

他在某个地方更详细地讨论了这一点,我想在他的原子<>武器演示中.基本上所有关于shared_ptr用例中需要内存栅栏的地方,而不是原子增量与减量的任何内在属性.

原因是你并不真正关心使用ref计数智能指针的增量的确切顺序,只要你没有错过任何但是减少,你必须有内存障碍,这样你的最终减量是至关重要的触发删除后,你没有任何可能的事情,从另一个线程到存储器被释放后被重新排序的智能指针所拥有的对象的先前存储器访问.


Mat*_*son 11

我认为它指的是增量可以"隐藏",其中"减量和检查"必须作为一个操作完成.

我不知道任何架构--counter(或者counter--,我们讨论的是像int,char等简单的数据类型)比++counteror 慢counter++.


Ada*_*son 9

Sutter所讨论的问题是,引用计数增量不需要任何后续操作来保证正确性.您将非零引用计数转换为另一个非零计数,因此无需进一步操作.但是,减量需要采取后续行动以确保正确性.递减将非零引用计数引用为非零或零引用计数,如果引用计数的减量变为零,则需要执行操作 - 具体而言,取消分配引用的对象.这种递减和动作动态需要更高的一致性,在栅栏级别(因此解除分配不会与CPU的内存/缓存管理逻辑重新排序的另一个核心上的某些其他读/写重新排序)和编译器级别(所以编译器没有'

因此,对于Sutter描述的场景,增量和减量之间的成本差异不在于基本操作本身,而是在对减量的实际使用(特别是对减量本身起作用)施加的一致性约束中适用于增量.