CPU缓存:两个地址之间的距离是否需要小于8个字节以获得缓存优势?

Lee*_*hai 5 caching cpu-architecture cpu-cache

这似乎是一个奇怪的问题..

假设缓存行的大小为64字节.此外,假设L1,L2,L3具有相同的高速缓存行大小(后称它是英特尔的Core i7的情况下).

内存上有两个对象A,B其(物理)地址相隔N个字节.为简单起见,我们假设A它位于缓存边界上,也就是说,它的地址是64的整数倍.

1)如果N<64,当ACPU取出时,B也会读入缓存.因此,如果B需要,并且高速缓存行尚未被驱逐,CPU将B在很短的时间内获取.大家都很开心.

2)如果N>> 64(即远大于64),当A被CPU取出时,B不会被读入缓存行A.所以我们说"CPU不喜欢追逐指针",这是避免堆分配基于节点的数据结构的原因之一std::list.

我的问题是,如果N> 64但是仍然很小,比如N= 70,换句话说,A并且B不适合一个缓存行但不是太远,当A由CPU加载时,取出B需要相同数量的时钟当N大于64 时,它会花费多少个周期?

改写 - 当A加载时,让t表示提取的时间B,t(N = 70)远小于或几乎等于t(N = 9999999)?

我问这个问题是因为我怀疑t(N = 70)远小于t(N = 9999999),因为CPU缓存是分层的.

如果有定量研究,那就更好了.

Pau*_*ton 5

至少有三个因素可以在 A 未命中后更快地获取 B。首先,处理器可能会推测性地获取下一个块(独立于任何基于步幅的预取引擎,这将取决于在时间和位置上彼此靠近的两次未命中以确定步幅;单位步幅预取不需要确定步幅值 [它是一个] 并且可以在第一次未命中后开始)。由于这种预取会消耗内存带宽和片上存储,因此它通常具有节流机制(这可以简单到具有中等大小的预取缓冲区,并且仅在内存接口足够空闲时才执行高度推测性的预取)。

其次,由于 DRAM 被组织成行并且改变行(在单个 bank 内)会增加延迟,如果 B 与 A 位于同一 DRAM 行中,则对 B 的访问可以避免行预充电的延迟(以关闭先前打开的行) 并激活(打开新行)。(这也可以提高内存带宽利用率。)

第三,如果 B 与 A 位于同一地址转换页面,则可以避免 TLB。(在许多设计中,相邻区域的分层页表遍历也更快,因为可以缓存分页结构。例如,在 x86-64 中,如果 B 与 A 位于相同的 2MiB 区域,TLB 未命中可能只需要执行一次内存访问因为页目录可能仍然被缓存;此外,如果 B 的转换与 A 的转换在同一个 64 字节缓存行中,并且 A 的 TLB 未命中是最近的,则缓存行可能仍然存在。)

在某些情况下,还可以通过将可能丢失的对象以固定的有序步长排列在一起来利用基于步长的预取引擎。这似乎是一个相当困难和有限的上下文优化。

stride 可以增加延迟的一种明显方式是引入冲突未命中。大多数缓存使用具有有限关联性的简单模 2 次幂索引,因此 2 次幂(或其他映射到同一缓存集)可以在有限数量的集合中放置不成比例的数据。一旦超过关联性,就会发生冲突未命中。(已经提出了倾斜关联性和非 2 的幂模索引来减少这个问题,但这些技术还没有被广泛采用。)

(顺便说一句,指针追逐特别慢的原因不仅仅是空间局部性低,而是因为存在数据依赖性,即无法在对A的访问完成后才能开始对B的访问,即获取B的延迟不能与获取 A 的延迟重叠。)