shared_ptrs 是不是由于引用计数器原子递增/递减而遇到缓存未命中?

Posted

技术标签:

【中文标题】shared_ptrs 是不是由于引用计数器原子递增/递减而遇到缓存未命中?【英文标题】:Do shared_ptrs encounter cache misses due to reference counter atomic increment/decrement?shared_ptrs 是否由于引用计数器原子递增/递减而遇到缓存未命中? 【发布时间】:2014-07-26 22:31:30 【问题描述】:

(这可能是原子增量/减量的一般问题,但我在shared_ptrs领域遇到过这种情况)

当原子引用计数器递增和递减时,shared_ptr 是否会遇到两次缓存行未命中/访问?

我确实找到了这个:

atomic operation cost

但似乎并没有太确定性......

更新

如果我运行一个循环数百万次,增加一个原子变量,我会得到 0.2 的 L1 缓存未命中率。如果我对非原子 int 做同样的事情,我会得到 0 L1 缓存未命中率.....

测试将暗示 L1 缓存行正在被驱逐。

【问题讨论】:

对不起,这不是一个答案。我不是原子操作方面的专家,我不会争论它们的成本有多大。但是,我可以争论调用这个操作的事实。我想知道在哪种情况下这对您很重要?如果指针是用 make_shared 创建的,显然缓存行与引用和数据将被读取一次,所以你可以说它少了一次缓存未命中。接下来,感谢 move 运算符,在移动 shared_ptr 时不会更改引用计数(例如,调整 std::vector 的大小)。 这并不完全正确。如果您的对象大于 cache_line_size 并且您读取了开头声明的数据成员,那么您最终会读取两次缓存行。 你是对的)虽然我认为这是一个罕见的情况。 【参考方案1】:

shared_ptr 必须将引用计数变量存储在某处。它很可能是从堆中分配的,并且 shared_ptr 包含指向该变量的指针。

完全有可能必须访问此变量会导致缓存操作,除非已将它们放在相同的块中,这是极不可能的。

如果您担心这对性能的影响,请创建一个具有整数的类来计算引用,一个使用它的自定义指针类,并从引用计数类派生您想要管理的每个类。

【讨论】:

以上是关于shared_ptrs 是不是由于引用计数器原子递增/递减而遇到缓存未命中?的主要内容,如果未能解决你的问题,请参考以下文章

智能指针是否线程安全

句柄而不是指针的引用计数

为什么多线程读写 shared_ptr 要加锁?

shared_ptr 上的原子操作

格式工厂shared_ptr

shared_ptr 引用计数