【发布时间】:2014-05-19 23:52:49
【问题描述】:
我有四个表示继承和组合层次结构的类:
class A{
//Structure here not important
}
class B : public A{
int a;
shared_ptr<C> c;
}
class C{
shared_ptr<D> d;
}
class D{
std::list<int> e;
}
然后我有一个vector<shared_ptr<A>>,但我迭代并从两个D std::list<int> 对象中求和*begin() 值:
for(int i = 0; i< vec.size(); i++){
shared_ptr<B> b = vec[i];
shared_ptr<C> c = b->c;
sum += *(c->d->e.begin());
}
我正在尝试计算每次循环迭代可以进行多少次单独的缓存行访问(如果我们假设每个级别的间接/指针存储在不同的缓存行中的最坏情况)。
到目前为止,我已经计算出每次迭代有 7.25 个不同的缓存行:
- 访问
shared_ptr<A>到vec[i](这是0.25,因为sizeof(shared_ptr<A>)/64) - 访问
A对象vec[i]指向 - 访问
shared_ptr<C>c 指向 - 访问
C对象c指向 - 访问 d 的
shared_ptr<D>对象 - 访问对象
D d - 访问
d的std::list<int> e指针 - 访问
d的*begin()数据
有什么我错过的吗?我不确定在循环内的堆栈上创建的对象(b 和 c)是否可以存储在不同的缓存行中,指向它们正在访问的指针(vec[i] 和 b->c)。
【问题讨论】:
-
一个 shared_ptr 对象管理 2 个指针——一个指向共享对象的指针加上一个指向共享状态信息的指针。共享状态包含 2 个原子值:强引用数和弱引用数。
-
@RichardHodges 啊,所以当访问 shared_ptrs 时,指向它们的引用计数对象的指针也可能导致单独的缓存行加载?
-
当然,如果您正在复制 shared_ptr 并因此增加共享计数。如果它只是纯粹的访问,我怀疑不是。这一行:
shared_ptr<C> c = b->c将导致复制,因此会导致间接 + 原子增量。通过返回参考来避免这种情况。 -
不,您只是取消引用智能指针,而不是在该行上创建它的副本。
-
注意
make_shared<T>分配T和ref counf数据是相邻的,而shared_ptr<T>(new T(blah))进行2次分配。
标签: c++ performance pointers cpu cpu-cache