2017-08-16 33 views
5

这似乎是一个奇怪的问题。CPU缓存:两个地址之间的距离是否需要小于8个字节以获得缓存优势?

假设缓存行的大小为64个字节。此外,假设L1,L2,L3具有相同的高速缓存行大小(this帖子称它是Intel Core i7的情况)。

存储器上有两个对象A,B,它们的(物理)地址是N字节。为简单起见,我们假设A是高速缓存器边界上,也就是它的地址是64。

1)如果N < 64的整数倍,当A是由CPU取出,B将被读入高速缓存,太。因此,如果需要B,并且高速缓存行尚未被驱逐,则CPU会在很短的时间内获取B。每个人都很高兴。 2)如果N >> 64(即远远大于64),当A被CPU提取时,B不会被读入高速缓存行,而是A。所以我们说“CPU不喜欢追逐指针”,这是避免堆分配的基于节点的数据结构的原因之一,如std::list

我的问题,如果N> 64,但仍然很小,说N = 70,换句话说,AB不适合在一个高速缓存行,但不会太远分开,当A是装通过CPU,提取B所花费的时钟周期数量与N远大于64时所花费的时钟周期数量相同?

改写 - 当被加载A,让表示取B的时间的经过,是Ñ = 70)远小于或几乎等于Ñ = 9999999)?

我问这个问题,因为我怀疑ñ = 70)比ñ = 9999999)要小得多,因为CPU缓存是层次

如果有定量研究,情况会更好。

回答

4

A失误越快,至少有三个因素可以使B取得。首先,处理器可以推测性地提取下一个块(独立于任何基于步长的预取引擎,这将取决于在时间和位置上彼此接近的两个未命中以确定步幅;单位步长预取不需要确定步幅值[这是一个],并且可以在第一次错过后开始)。由于这种预取消耗内存带宽和片上存储,因此它通常具有调节机制(其可以像具有适度大小的预取缓冲区一样简单并且只在存储器接口充分空闲时进行高度推测预取)。其次,由于DRAM被组织成行并且(在单个存储体内)改变行增加了延迟,如果B与A在相同的DRAM行中,则对B的访问可以避免行预充电的延迟(关闭先前打开的行)并激活(打开新行)。 (这也可以提高内存带宽利用率。)

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

在某些情况下,还可以通过安排可能错过固定的有序步幅的对象来利用跨步预取引擎。这似乎是一个相当困难和有限的上下文优化。

一个明显的方式,即迈步可以增加延迟是通过引入冲突未命中。大多数高速缓存使用简单的模联合有限性的两个索引的功能,所以两个步幅的功率(或对同一个高速缓存集的其他映射)可以将不成比例的数据放置在有限数量的集合中。一旦超过关联性,就会发生冲突缺失。 (已经提出偏斜相关性和非幂次模2索引来减少这个问题,但是这些技术还没有被广泛采用。)

(顺便说一下,原因指针追逐特别慢并不仅仅是低的空间局部性,但是直到访问A完成之后才能开始对B的访问,因为存在数据依赖性,即,获取B的等待时间不能与获取A的等待时间重叠。)

+0

所以..简而言之,t(N = 70)最可能小于t(N = 999999),对吧? – user8385554

+1

@ user8385554是的。它倾向于具有TLB命中并且可能利用推测预取下一个高速缓存行,甚至可能利用仍然打开的DRAM行(如果A和B未命中靠近)。如果A命中L3,TLB的好处可能是主/唯一一次(下一行预取很可能在内存控制器完成,并且DRAM行不会被激活来访问A)。如果B在不同的页面上(x86上带有基页的4 KiB边界),则没有任何好处可用。 –

2

如果B的地址比A低,即使它们相邻,也不会在同一个高速缓存行中。所以你的N < 64的情况是错误的:它确实是“相同的缓存行”的情况。


既然你提到的英特尔酷睿i7:SandyBridge的家庭在L2,这(如果没有大量的已经很卓越的未命中)预取其他高速缓存行一对,完成了“空间”预取自然对齐的128B对线。

从英特尔优化手册,在2.3节的Sandy Bridge:

2.3.5.4 Data Prefetching

  • ...一些预取器读取到L1。

  • 空间预取:该预取努力完成每高速缓存行提取到L2高速缓存与 ,它完成对一个128字节对齐组块中的一对线。

  • ...等几个预取尝试预取到L2

IDK它是如何尽快做到这一点;如果它在第一个缓存行到达之前不发出请求,那么对于追踪指针的案例来说,这无关紧要。如果缓存行到达L1D时,依赖加载只能执行几个周期,如果它真的只是指针追踪而没有一堆计算延迟。但是如果它在第一次未命中(包含第二次加载的地址)之后不久发出预取,则第二次加载可以在L1D高速缓存中找到它的数据,在第一次请求加载之后到达一个或两个周期。

无论如何,这使得128B的边界与Intel CPU中的预取有关。


查看Paul对其他因素的优秀答案。