【问题标题】:How many objects iterable in a vector before L3 cache misses occur?在发生 L3 缓存未命中之前,向量中有多少可迭代对象?
【发布时间】:2014-05-19 19:06:49
【问题描述】:

假设我有一个包含堆分配内存的数据成员的类:

class X{
    std::map<int, double> a;
    std::set<int> b;
    std::vector<int>;
    std::string c;
}

我有一个 std::vector&lt;shared_ptr&lt;X&gt;&gt; 包含许多这些 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。第一次使用内存时,您将永远怀念。
  • L3 缓存命中和主内存命中之间的时间差异有多明显?它们应该相当接近,而 L2(通常约为 256kiB)和 L3 之间的差异通常成比例地更大。
  • 另外,您的术语已关闭。通常,“DRAM 未命中”意味着页面错误/命中交换,而“缓存未命中”意味着必须进入主内存,因为缓存中没有匹配/命中。
  • 除非您的进程具有对 CPU 的独占访问权限,否则我想 L3 将填充来自其他程序的内容...
  • 为了访问数据,您还遵循了几个指针间接寻址。这些可能分散在内存中并导致大量缓存未命中。

标签: c++ performance cpu shared-ptr cpu-architecture


【解决方案1】:

在 Intel CPU 上,您可以使用 Intel Architecture Code Analyzer (IACA) 来分析您的循环。如果我没记错的话,如果你配置得当,它还可以分析缓存未命中等。

另一个工具是 Valgrind,它是一个模拟器,如果配置正确,它也可以用来模拟缓存行为。

但总的来说 - 为了最大限度地使用缓存 - 您应该将迭代的数据分离到一个线性数组中(并且尽可能小)。例如。如果可能的话,一个带有键(或您迭代的数据)的数组和一个带有其余部分的数组。所以简而言之,只有当您迭代的数据的地址是线性排序的,而不是随机访问时,缓存才会真正发挥作用,因为如果您迭代分配在堆上不同位置的许多对象,就会得到随机访问。

【讨论】:

    猜你喜欢
    • 2020-05-19
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 2012-05-11
    • 2013-08-03
    • 2017-09-26
    相关资源
    最近更新 更多