假设我有一个包含堆分配内存的数据成员的类:
class X{
std::map<int, double> a;
std::set<int> b;
std::vector<int>;
std::string c;
}
我有一个std::vector<shared_ptr<X>>
包含许多这些X
个对象,我将遍历并访问map.begin():
for(int i =0; i<vec.size(); i++){
running_total += *(vec[i]->a.begin());
}
理论上,在遇到L3缓存未命中之前,我应该能够在向量中保存/迭代多少个对象?
我认为答案是L3缓存可容纳的每个对象有多少缓存行,但L3 size / sizeof(x_element.get())似乎没有给出我从分析中看到的答案....
我的L3缓存是8MB,每个缓存行是64字节,因此在L3缓存未命中之前我可以容纳大约125,000个对象。但是我看到L3缓存未命中的矢量元素数量要少得多。
答案 0 :(得分:1)
在Intel CPU上,您可以使用Intel Architecture Code Analyzer (IACA)来分析循环。如果我没记错的话,如果你正确配置它也可以分析缓存未命中等等。
另一个工具是Valgrind,它是一个模拟器,如果你正确配置它也可以用来模拟缓存行为。
但总的来说 - 为了最大化缓存使用率 - 您应该将在一个线性数组中迭代的数据分开(并尽可能小)。例如。一个数组包含键(或迭代的数据)和一个数组,其余如果可能。因此,简而言之,只有当您迭代的数据的地址是线性排序而不是随机访问时,如果迭代堆上不同位置分配的许多对象,缓存才会真正启动。