【问题标题】:How much data is loaded in to the L2 and L3 caches?有多少数据加载到 L2 和 L3 缓存中?
【发布时间】:2014-05-26 07:35:35
【问题描述】:

如果我有这门课:

class MyClass{
    short a;
    short b;
    short c;
};

我有这段代码在上面执行计算:

std::vector<MyClass> vec;
//
for(auto x : vec){
    sum = vec.a * (3 + vec.b) / vec.c;
}

我知道 CPU 只从 L1 缓存中加载它需要的数据,但是当 L1 缓存从 L2 缓存中检索数据时,它会加载整个“缓存行”(其中可能包含它不包含的几个字节的数据)不需要)。

L2 缓存从 L3 缓存加载多少数据,而 L3 缓存从主内存加载多少数据? 是否按页面定义,如果是,此答案将如何根据不同的 L2/L3 缓存大小?

【问题讨论】:

  • 顺便说一句,如果你没有除法,我建议使用向量/数组的结构而不是向量/数组的结构组织。这样可以方便地使用 SIMD 指令。不幸的是,大多数 ISA 不包括 SIMD 除法,最多提供(并行)单精度 FP 倒数估计指令,可以与 Newton-Raphson 一起使用来执行除法,因此 SIMD 操作可能没有帮助。

标签: performance caching optimization cpu cpu-architecture


【解决方案1】:

L2 和 L3 高速缓存也具有小于虚拟内存系统页面的高速缓存行。 L2 和 L3 缓存线的大小大于或等于 L1 缓存线大小,通常是 L1 缓存线大小的两倍。

对于最近的 x86 处理器,所有缓存都使用相同的 64 字节缓存行大小。 (早期的 Pentium 4 处理器有 64 字节的 L1 缓存线和 128 字节的 L2 缓存线。)

IBM 的 POWER7 在 L1、L2 和 L3 中使用 128 字节缓存块。 (然而,POWER4 在 L1 和 L2 中使用 128 字节块,但在片外 L3 中对 512 字节块进行扇区化。扇区化块为子块提供有效位。对于 L2 和 L3 高速缓存,扇区化允许单个相干大小为在整个系统中使用。)

在末级高速缓存中使用更大的高速缓存行大小可减少标记开销并促进处理器和主内存之间的长突发访问(更长的突发可提供更多带宽并促进更广泛的纠错和 DRAM 芯片冗余),同时允许其他级别缓存和缓存一致性以使用较小的块,从而减少带宽使用和容量浪费。 (大的末级缓存块也提供了预取效果,由于末级缓存的容量相对较高,因此缓存污染问题不太严重。但是,硬件预取可以实现相同的效果,同时减少缓存容量的浪费。)使用较小的缓存(例如,典型的 L1 缓存),驱逐发生得更频繁,因此可以利用空间局部性的时间跨度更小(即,更有可能在缓存行被驱逐之前仅使用一个较小块中的数据)。更大的缓存行也减少了可用块的数量,在某种意义上降低了缓存的容量;这种容量减少对于小型缓存来说尤其成问题。

【讨论】:

    【解决方案2】:

    这在一定程度上取决于您平台的 ISA 和微架构。最近基于 x86-64 的微架构在缓存层次结构的所有级别中使用 64 字节行。

    通常有符号的短裤每个都需要两个字节,这意味着 MyClass 除了类开销外还需要 6 个字节。如果您的 C++ 实现将 vector 像数组一样连续存储,则每 64 字节行应该获得大约 10 个 MyClass 对象。只要向量 的长度合适,就不会加载太多垃圾。

    请注意,由于您正在以非常可预测的模式访问元素,因此硬件预取器应该启动并获取它期望在未来使用的合理数量的数据。这可能会为缓存层次结构的各个级别带来超出您需要的内容。它会因芯片而异。

    【讨论】:

      猜你喜欢
      • 2014-05-15
      • 2020-05-19
      • 2014-07-04
      • 2017-09-26
      • 1970-01-01
      • 2017-03-10
      • 2014-02-16
      • 2016-07-15
      • 1970-01-01
      相关资源
      最近更新 更多