作者:井爱3053_170 | 来源:互联网 | 2022-11-28 09:00
我正在阅读有关Intel Core i7系统中可用的不同预取器的信息。我进行了实验,以了解何时调用这些预取器。
这些是我的发现
L1 IP预取器在3次高速缓存未命中后开始预取。它仅在缓存命中时预取。
L2相邻行预取器在第一个高速缓存未命中后开始预取,并在高速缓存未命中时预取。
L1 H / W(跨步)预取器在第一次高速缓存未命中后开始预取,并在高速缓存命中时进行预取。
我无法了解DCU预取器的行为。它何时开始预取或调用?它是否在缓存命中或未命中时预取下一个缓存行?
我在其中提到的英特尔文档披露-hw-prefetcher中进行了探索-DCU预取器将下一个缓存行提取到L1-D缓存中,但是在开始预取时没有明确的信息。
谁能解释DCU预取器何时开始预取?
1> Hadi Brais..:
DCU预取器不会以确定性方式预取行。它似乎具有与每个潜在的预取请求关联的置信度值。如果置信度仅大于某个阈值,则将触发预取。而且,似乎如果两个L1预取器都启用,则它们中只有一个可以在同一周期内发出预取请求。也许可以接受较高信任度的预取。下面的答案没有考虑这些观察结果。(需要做更多的实验工作。将来我会重写它。)
英特尔手册向我们介绍了有关DCU预取器的一些信息。优化手册的第2.4.5.4节和第2.5.4.2节都说以下几点:
数据缓存单元(DCU)预取器-此预取器,也称为流式预取器,是由对最近加载的数据的递增访问触发的。处理器假定此访问权限是流算法的一部分,并自动获取下一行。
请注意,第2.4.5.4节是Sandy Bridge一节的一部分,而2.5.4.2节是Intel Core一节的一部分。DCU预取程序首先在Intel Core微体系结构上受支持,并且在以后的所有微体系结构中也受支持。据我所知,没有迹象表明DCU预取器已经随着时间而改变。因此,我认为至少在所有微架构(直到Skylake)上它都完全相同。
那句话并没有说太多。“升序访问”部分建议预取器由偏移量增加的多次访问触发。“最近加载的数据”部分含糊不清。它可能指的是紧接在地址空间中要预取的行之前的一个或多个行。还不清楚这是指虚拟地址还是物理地址。“获取下一行”部分表明,每次触发时,它仅获取一行,并且该行是触发预取的行之后的行。
我在Haswell上进行了一些实验,所有Df预取器都禁用了,所有预取器均被禁用。我还禁用了超线程。这使我能够独立研究DCU预取器。结果显示如下:
DCU预取器最多跟踪4个不同的4KB(可能是物理)页面的访问。
当对同一高速缓存集内的一条或多条线进行三个或更多访问时,将触发DCU预取器。访问必须是需求加载或软件预取(包括在内的任何预取指令prefetchnta
)或两者的组合。访问可以是L1D中的命中或未命中,或者是两者的组合。触发后,对于当前正在跟踪的4个页面,它将预取每个页面中的下一行。例如,请考虑以下三个需求负载缺失:0xF1000、0xF2008和0xF3004。假设要跟踪的4个页面是0xF1000、0xF2000、0xF3000和0xF4000。然后,DCU预取器将预取以下行:0xF1040、0xF2040、0xF3040和0xF4040。
当对两个连续的高速缓存集中的一个或多个行进行三个或更多访问时,将触发DCU预取器。像以前一样,访问必须是需求负载或软件预取。访问可以是L1D中的命中或未命中。触发后,对于当前正在跟踪的4个页面,它将预取每个页面中的下一行相对于具有较小物理地址的被访问的高速缓存集的各个页面的大小。例如,请考虑以下三个需求负载缺失:0xF1040、0xF2048和0xF3004。假设要跟踪的4个页面是0xF1000、0xF2000、0xF3000和0xF4000。然后,DCU预取器将预取以下行:0xF3040和0xF4040。无需预取0xF1040或0xF2040,因为已经有请求。
预取器将不会预取到下一个4KB页面。因此,如果这三个访问是对页面最后一行的访问,则不会触发预取器。
如下选择要跟踪的页面。每当需求负载或软件预取访问页面时,都会跟踪该页面,它将替换当前正在跟踪的4个页面之一。我没有进一步研究用于确定要替换4页中的哪一页的算法。这可能很简单。
当由于上一个项目符号点中提到的类型的访问而导致对新页面的跟踪时,同一页面和同一行至少需要两次访问触发预取器预取下一行。否则,如果L1中尚不存在对下一行的后续访问,则会丢失该行。之后,无论哪种方式,DCU预取器的行为都如第二和第三项目要点所述。例如,请考虑以下三个需求负载缺失:0xF1040、0xF2048和0xF3004。对同一行有两次访问,第三个访问相同的缓存集,但访问的行不同。这些访问将使DCU预取器跟踪两个页面,但不会立即触发它。当预取程序看到对同一缓存集中的任何一行的另外三个访问时,它将为当前正在跟踪的那些页面预取下一行。作为另一个示例,请考虑以下三个需求负载丢失:0xF1040、0xF2048和0xF3030。
在我看来,预取器正在从正在访问的页面的页面表条目(从TLB)接收脏标志。该标志指示页面是否脏。如果脏了,则预取程序将不会跟踪页面,并且对页面的访问将不计入满足触发条件的三个访问中。因此,似乎DCU预取器只是忽略脏页。就是说,尽管预取器支持该页面,但该页面不必是只读的。但是,需要进行更彻底的调查才能更准确地了解存储如何与DCU预取器交互。
因此,触发预取程序的访问不必“升序”或遵循任何顺序。高速缓存行偏移量本身似乎被预取器忽略。仅物理页码很重要。
我认为DCU预取器具有包含4个条目的完全关联缓冲区。每个条目都标记有(可能是物理的)页码,并具有一个有效位来指示该条目是否包含有效的页码。此外,L1D的每个高速缓存集都与一个2位饱和计数器关联,每当需求负载或软件预取请求访问相应的高速缓存集且未设置所访问页面的脏标志时,该计数器就会递增。当计数器的值达到3时,将触发预取器。预取器已经具有需要从中进行预取的物理页码。它可以从与计数器相对应的缓冲区条目中获取它们。因此,它可以立即为缓冲区所跟踪的每个页面的下一个缓存行发出预取请求。然而,如果填充缓冲区不可用于触发的预取请求,则将删除预取。然后计数器将重置为零。页表可能会被修改。每当刷新TLB时,预取器就有可能刷新其缓冲区。
可能是有两个DCU预取器,每个逻辑核心一个。禁用超线程时,也会禁用其中一个预取器。也可能是包含页码的4个缓冲区条目在两个逻辑核心之间静态分区,并且在禁用超线程时组合在一起。我不确定,但是这种设计对我来说很有意义。另一种可能的设计是每个预取器都有一个专用的4入口缓冲区。启用超线程后,不难确定DCU预取器的工作方式。我只是没有花精力去研究它。
总而言之,DCU预取器是迄今为止在现代高性能英特尔处理器中可用的4种数据预取器中最简单的一种。似乎仅当顺序但缓慢地访问少量只读数据(例如只读文件和静态初始化的全局数组)或同时访问可能包含许多小字段的多个只读对象时,此方法才有效并跨越同一页面中的几个连续的缓存行。
第2.4.5.4节还提供了有关L1D预取的其他一般信息,因此适用于DCU预取器。
满足以下条件时,数据预取由装入操作触发:
负载来自回写内存类型。
这意味着DCU预取器将不会跟踪对WP和WT可缓存内存类型的访问。
预取的数据与触发它的加载指令在同一4K字节页内。
这已经通过实验验证。
管道中没有围栏。
我不知道这是什么意思。请参阅:https : //software.intel.com/zh-cn/forums/software-tuning-performance-optimization-platform-monitoring/topic/805373。
没有太多其他未命中负载。
只有10个填充缓冲区可以容纳未命中L1D的请求。这提出了一个问题,尽管如果只有一个可用的填充缓冲区,那么硬件预取器将使用它还是将其留给预期的需求访问?我不知道。
没有连续的商店流。
这表明,如果有大量的商店与很少的负载交织在一起,那么L1预取器将忽略负载,并基本上暂时关闭,直到商店变成少数。但是,我的实验结果表明,即使将单个存储到页面上,也会关闭该页面的预取器。
所有Intel Atom微体系结构都具有DCU预取器。尽管预取程序在这些微体系结构中可能跟踪不到4页。
直到Knights Landing为止的所有Xeon Phi微体系结构都没有DCU预取器。我不知道后来的至强融核微体系结构。