DCU 预取器在什么情况下开始预取?
In which condition DCU prefetcher start prefetching?
我正在阅读有关 Intel Core i7 系统中可用的不同预取器的信息。
我已经进行了实验以了解何时调用这些预取器。
这些是我的发现
L1 IP 预取器在 3 次缓存未命中后开始预取。它只是
缓存命中时预取。
L2 相邻行预取器在第一次缓存未命中后开始预取
并在缓存未命中时预取。
L2 H/W (stride) 预取器在第一次缓存未命中后开始预取
并在缓存命中时预取。
我无法理解 DCU 预取器的行为。什么时候开始预取或调用?它是否在缓存命中或未命中时预取下一个缓存行?
我研究了英特尔文档 disclosure-of-hw-prefetcher,其中提到 - DCU 预取器将下一个缓存行提取到 L1-D 缓存中,但在开始预取时没有明确的信息。
谁能解释一下 DCU 预取器 prefetch 何时开始预取?
据我所知,英特尔 CPU 没有 L1 相邻线预取器。
它在 L2 中有一个,它试图完成一对 128 字节对齐的 64 字节缓存行。 (所以它不一定是下一行,如果导致一行被缓存的需求未命中或其他预取是针对一对的高半部分,则它可能是上一行。)
另见 https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/714832, and the many "related" links here on SO, e.g. prefetching data at L1 and L2. Not sure if either of those have any more details than the prefetch section of Intel's optimization manual, though: https://software.intel.com/en-us/articles/intel-sdm#optimization
我不确定它是否有任何启发式方法可以在只需要一对行中的一个时避免浪费带宽和缓存占用空间,而不是在有足够多的需求未命中时不预取。
DCU 预取器不会以确定的方式预取行。它似乎具有与每个潜在预取请求关联的置信度值。只有当置信度大于某个阈值时才会触发预取。而且,似乎如果启用了两个L1预取器,则只有其中一个可以在同一周期内发出预取请求。也许接受来自具有更高置信度的预取。下面的答案没有考虑这些观察结果。 (还有很多实验工作需要做,以后会重写的。)
英特尔手册告诉我们一些关于 DCU 预取器的事情。优化手册第2.4.5.4节和第2.5.4.2节都是这样说的:
Data cache unit (DCU) prefetcher -- This prefetcher, also known as the
streaming prefetcher, is triggered by an ascending access to very
recently loaded data. The processor assumes that this access is part
of a streaming algorithm and automatically fetches the next line.
请注意,第 2.4.5.4 节是 Sandy Bridge 部分的一部分,第 2.5.4.2 节是 Intel Core 部分的一部分。 DCU 预取器首先在 Intel Core 微架构上得到支持,并且在所有后来的微架构上也得到支持。据我所知,没有迹象表明 DCU 预取器随时间发生了变化。所以我认为它至少在 Skylake 之前的所有微架构上都完全相同。
这句话并没有说明什么。 "ascending access" 部分表明预取器是由偏移量增加的多次访问触发的。 "recently loaded data" 部分含糊不清。它可以引用紧接在地址 space 中要预取的行之前的一行或多行。也不清楚这是指虚拟地址还是物理地址。 "fetches the next line" 部分表明它每次触发时只获取一行,并且该行是触发预取的行之后的行。
我在 Haswell 上进行了一些实验,禁用了除 DCU 预取器之外的所有预取器。我还禁用了超线程。这使我能够单独研究 DCU 预取器。结果显示如下:
- DCU 预取器跟踪最多 4 个不同的 4KB(可能是物理)页面的访问。
- 当对同一缓存集中的一个或多个行进行三次或更多次访问时,将触发DCU预取器。访问必须是按需加载或软件预取(任何预取指令,包括
prefetchnta
)或两者的组合。访问可以是 L1D 中的命中或未命中或两者的组合。当它被触发时,对于当前正在跟踪的 4 个页面,它将在相应页面的 each 内预取紧邻的下一行。例如,考虑以下三个需求负载未命中:0xF1000、0xF2008 和 0xF3004。假设被跟踪的 4 个页面是 0xF1000、0xF2000、0xF3000 和 0xF4000。然后 DCU 预取器将预取以下行:0xF1040、0xF2040、0xF3040 和 0xF4040。
- 当对两个连续缓存集中的一个或多个行进行三次或更多次访问时,将触发DCU预取器。就像以前一样,访问必须是按需加载或软件预取。 L1D 中的访问可以是命中或未命中。当它被触发时,对于当前正在跟踪的 4 个页面,它会预取相应页面的 each 中的下一行,相对于具有较小物理地址的访问缓存集.例如,考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3004。假设被跟踪的 4 个页面是 0xF1000、0xF2000、0xF3000 和 0xF4000。然后 DCU 预取器将预取以下行:0xF3040 和 0xF4040。不需要预取 0xF1040 或 0xF2040,因为已经有对它们的请求。
- 预取器不会预取到下一个 4KB 页面。所以如果三个访问都是到页面的最后一行,则不会触发prefetcher。
- 要跟踪的页面选择如下。每当需求加载或软件预取访问页面时,该页面将被跟踪,并将替换当前正在跟踪的 4 个页面之一。我没有进一步研究用于决定替换 4 个页面中的哪一个的算法。虽然它可能很简单。
- 当新页面由于上一个要点中提到的类型的访问而被跟踪时,至少需要两次访问到同一页面和同一行到触发预取器预取下一行。否则,如果该行不存在,则对下一行的后续访问将在 L1 中丢失。之后,无论哪种方式,DCU 预取器的行为都如第二和第三点中所述。例如,考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3004。有两次访问同一行,第三次访问相同的缓存集但不同的行。这些访问将使 DCU 预取器跟踪这两个页面,但它不会立即触发它。当预取器看到另外三个访问同一缓存集中的任何行时,它将为当前正在跟踪的那些页面预取下一行。作为另一个示例,请考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3030。这些访问都在同一行,因此它们不仅会使预取器跟踪页面,还会触发该页面和任何其他已被跟踪的页面的下一行预取。
- 在我看来,预取器正在从正在访问的页面的页面 table 条目(来自 TLB)接收脏标志。该标志指示页面是否脏。如果它是脏的,预取器将不会跟踪页面并且对该页面的访问不会被计入满足触发条件的三次访问。所以看起来 DCU 预取器只是简单地忽略了脏页。也就是说,尽管预取程序支持该页面,但它不必是只读的。但是,需要进行更彻底的调查以更准确地了解存储如何与 DCU 预取器交互。
因此触发预取器的访问不必是 "ascending" 或遵循任何顺序。缓存行偏移量本身似乎被预取器忽略了。只有物理页码很重要。
我认为 DCU 预取器有一个包含 4 个条目的完全关联缓冲区。每个条目都标有(可能是物理的)页码,并且有一个有效位来指示该条目是否包含有效的页码。此外,L1D 的每个缓存集都与一个 2 位饱和计数器相关联,每当需求加载或软件预取请求访问相应的缓存集并且未设置被访问页面的脏标志时,该计数器就会递增。当计数器达到值 3 时,触发预取器。预取器已经有了它需要预取的物理页码;它可以从计数器对应的缓冲区条目中获取它们。因此它可以立即向缓冲区跟踪的每个页面的下一个缓存行发出预取请求。但是,如果填充缓冲区对于触发的预取请求不可用,则预取将被丢弃。然后计数器将重置为零。不过,第 table 页可能会被修改。每当刷新 TLB 时,预取器可能会刷新其缓冲区。
可能存在两个 DCU 预取器,每个逻辑核心一个。当禁用超线程时,其中一个预取器也将被禁用。也可能是包含页码的 4 个缓冲区条目在两个逻辑核心之间静态分区,并在禁用超线程时合并。我不确定,但这样的设计对我来说很有意义。另一种可能的设计是每个预取器都有一个专用的 4 条目缓冲区。不难确定启用超线程时 DCU 预取器的工作方式。就是没花功夫去研究
总而言之,DCU 预取器是现代高性能英特尔处理器中可用的 4 种数据预取器中最简单的。似乎只有在顺序但缓慢地访问小块只读数据(例如只读文件和静态初始化的全局数组)或同时访问多个可能包含许多小字段的只读对象时才有效并跨越同一页中的几个连续缓存行。
第 2.4.5.4 节还提供了有关一般 L1D 预取的附加信息,因此它适用于 DCU 预取器。
Data prefetching is triggered by load operations when the following
conditions are met:
- Load is from writeback memory type.
这意味着 DCU 预取器将不会跟踪对 WP 和 WT 可缓存内存类型的访问。
- The prefetched data is within the same 4K byte page as the load instruction that triggered it.
这已经通过实验验证。
- No fence is in progress in the pipeline.
我不知道这是什么意思。参见:https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/805373.
- Not many other load misses are in progress.
只有 10 个填充缓冲区可以容纳错过 L1D 的请求。这提出了一个问题,如果只有一个可用的填充缓冲区,硬件预取器会使用它还是将其留给预期的需求访问?我不知道。
- There is not a continuous stream of stores.
这表明如果有大量商店与少量负载交织在一起,L1 预取器将忽略负载并基本上暂时关闭,直到商店成为少数。然而,我的实验结果表明,即使是单个存储到页面也会关闭该页面的预取器。
所有英特尔凌动微架构都具有 DCU 预取器。尽管预取器可能会跟踪这些微体系结构中少于 4 个页面。
包括 Knights Landing 在内的所有 Xeon Phi 微体系结构都没有 DCU 预取器。我不知道以后的 Xeon Phi 微架构。
我正在阅读有关 Intel Core i7 系统中可用的不同预取器的信息。 我已经进行了实验以了解何时调用这些预取器。
这些是我的发现
L1 IP 预取器在 3 次缓存未命中后开始预取。它只是 缓存命中时预取。
L2 相邻行预取器在第一次缓存未命中后开始预取 并在缓存未命中时预取。
L2 H/W (stride) 预取器在第一次缓存未命中后开始预取 并在缓存命中时预取。
我无法理解 DCU 预取器的行为。什么时候开始预取或调用?它是否在缓存命中或未命中时预取下一个缓存行?
我研究了英特尔文档 disclosure-of-hw-prefetcher,其中提到 - DCU 预取器将下一个缓存行提取到 L1-D 缓存中,但在开始预取时没有明确的信息。
谁能解释一下 DCU 预取器 prefetch 何时开始预取?
据我所知,英特尔 CPU 没有 L1 相邻线预取器。
它在 L2 中有一个,它试图完成一对 128 字节对齐的 64 字节缓存行。 (所以它不一定是下一行,如果导致一行被缓存的需求未命中或其他预取是针对一对的高半部分,则它可能是上一行。)
另见 https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/714832, and the many "related" links here on SO, e.g. prefetching data at L1 and L2. Not sure if either of those have any more details than the prefetch section of Intel's optimization manual, though: https://software.intel.com/en-us/articles/intel-sdm#optimization
我不确定它是否有任何启发式方法可以在只需要一对行中的一个时避免浪费带宽和缓存占用空间,而不是在有足够多的需求未命中时不预取。
DCU 预取器不会以确定的方式预取行。它似乎具有与每个潜在预取请求关联的置信度值。只有当置信度大于某个阈值时才会触发预取。而且,似乎如果启用了两个L1预取器,则只有其中一个可以在同一周期内发出预取请求。也许接受来自具有更高置信度的预取。下面的答案没有考虑这些观察结果。 (还有很多实验工作需要做,以后会重写的。)
英特尔手册告诉我们一些关于 DCU 预取器的事情。优化手册第2.4.5.4节和第2.5.4.2节都是这样说的:
Data cache unit (DCU) prefetcher -- This prefetcher, also known as the streaming prefetcher, is triggered by an ascending access to very recently loaded data. The processor assumes that this access is part of a streaming algorithm and automatically fetches the next line.
请注意,第 2.4.5.4 节是 Sandy Bridge 部分的一部分,第 2.5.4.2 节是 Intel Core 部分的一部分。 DCU 预取器首先在 Intel Core 微架构上得到支持,并且在所有后来的微架构上也得到支持。据我所知,没有迹象表明 DCU 预取器随时间发生了变化。所以我认为它至少在 Skylake 之前的所有微架构上都完全相同。
这句话并没有说明什么。 "ascending access" 部分表明预取器是由偏移量增加的多次访问触发的。 "recently loaded data" 部分含糊不清。它可以引用紧接在地址 space 中要预取的行之前的一行或多行。也不清楚这是指虚拟地址还是物理地址。 "fetches the next line" 部分表明它每次触发时只获取一行,并且该行是触发预取的行之后的行。
我在 Haswell 上进行了一些实验,禁用了除 DCU 预取器之外的所有预取器。我还禁用了超线程。这使我能够单独研究 DCU 预取器。结果显示如下:
- DCU 预取器跟踪最多 4 个不同的 4KB(可能是物理)页面的访问。
- 当对同一缓存集中的一个或多个行进行三次或更多次访问时,将触发DCU预取器。访问必须是按需加载或软件预取(任何预取指令,包括
prefetchnta
)或两者的组合。访问可以是 L1D 中的命中或未命中或两者的组合。当它被触发时,对于当前正在跟踪的 4 个页面,它将在相应页面的 each 内预取紧邻的下一行。例如,考虑以下三个需求负载未命中:0xF1000、0xF2008 和 0xF3004。假设被跟踪的 4 个页面是 0xF1000、0xF2000、0xF3000 和 0xF4000。然后 DCU 预取器将预取以下行:0xF1040、0xF2040、0xF3040 和 0xF4040。 - 当对两个连续缓存集中的一个或多个行进行三次或更多次访问时,将触发DCU预取器。就像以前一样,访问必须是按需加载或软件预取。 L1D 中的访问可以是命中或未命中。当它被触发时,对于当前正在跟踪的 4 个页面,它会预取相应页面的 each 中的下一行,相对于具有较小物理地址的访问缓存集.例如,考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3004。假设被跟踪的 4 个页面是 0xF1000、0xF2000、0xF3000 和 0xF4000。然后 DCU 预取器将预取以下行:0xF3040 和 0xF4040。不需要预取 0xF1040 或 0xF2040,因为已经有对它们的请求。
- 预取器不会预取到下一个 4KB 页面。所以如果三个访问都是到页面的最后一行,则不会触发prefetcher。
- 要跟踪的页面选择如下。每当需求加载或软件预取访问页面时,该页面将被跟踪,并将替换当前正在跟踪的 4 个页面之一。我没有进一步研究用于决定替换 4 个页面中的哪一个的算法。虽然它可能很简单。
- 当新页面由于上一个要点中提到的类型的访问而被跟踪时,至少需要两次访问到同一页面和同一行到触发预取器预取下一行。否则,如果该行不存在,则对下一行的后续访问将在 L1 中丢失。之后,无论哪种方式,DCU 预取器的行为都如第二和第三点中所述。例如,考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3004。有两次访问同一行,第三次访问相同的缓存集但不同的行。这些访问将使 DCU 预取器跟踪这两个页面,但它不会立即触发它。当预取器看到另外三个访问同一缓存集中的任何行时,它将为当前正在跟踪的那些页面预取下一行。作为另一个示例,请考虑以下三个需求负载未命中:0xF1040、0xF2048 和 0xF3030。这些访问都在同一行,因此它们不仅会使预取器跟踪页面,还会触发该页面和任何其他已被跟踪的页面的下一行预取。
- 在我看来,预取器正在从正在访问的页面的页面 table 条目(来自 TLB)接收脏标志。该标志指示页面是否脏。如果它是脏的,预取器将不会跟踪页面并且对该页面的访问不会被计入满足触发条件的三次访问。所以看起来 DCU 预取器只是简单地忽略了脏页。也就是说,尽管预取程序支持该页面,但它不必是只读的。但是,需要进行更彻底的调查以更准确地了解存储如何与 DCU 预取器交互。
因此触发预取器的访问不必是 "ascending" 或遵循任何顺序。缓存行偏移量本身似乎被预取器忽略了。只有物理页码很重要。
我认为 DCU 预取器有一个包含 4 个条目的完全关联缓冲区。每个条目都标有(可能是物理的)页码,并且有一个有效位来指示该条目是否包含有效的页码。此外,L1D 的每个缓存集都与一个 2 位饱和计数器相关联,每当需求加载或软件预取请求访问相应的缓存集并且未设置被访问页面的脏标志时,该计数器就会递增。当计数器达到值 3 时,触发预取器。预取器已经有了它需要预取的物理页码;它可以从计数器对应的缓冲区条目中获取它们。因此它可以立即向缓冲区跟踪的每个页面的下一个缓存行发出预取请求。但是,如果填充缓冲区对于触发的预取请求不可用,则预取将被丢弃。然后计数器将重置为零。不过,第 table 页可能会被修改。每当刷新 TLB 时,预取器可能会刷新其缓冲区。
可能存在两个 DCU 预取器,每个逻辑核心一个。当禁用超线程时,其中一个预取器也将被禁用。也可能是包含页码的 4 个缓冲区条目在两个逻辑核心之间静态分区,并在禁用超线程时合并。我不确定,但这样的设计对我来说很有意义。另一种可能的设计是每个预取器都有一个专用的 4 条目缓冲区。不难确定启用超线程时 DCU 预取器的工作方式。就是没花功夫去研究
总而言之,DCU 预取器是现代高性能英特尔处理器中可用的 4 种数据预取器中最简单的。似乎只有在顺序但缓慢地访问小块只读数据(例如只读文件和静态初始化的全局数组)或同时访问多个可能包含许多小字段的只读对象时才有效并跨越同一页中的几个连续缓存行。
第 2.4.5.4 节还提供了有关一般 L1D 预取的附加信息,因此它适用于 DCU 预取器。
Data prefetching is triggered by load operations when the following conditions are met:
- Load is from writeback memory type.
这意味着 DCU 预取器将不会跟踪对 WP 和 WT 可缓存内存类型的访问。
- The prefetched data is within the same 4K byte page as the load instruction that triggered it.
这已经通过实验验证。
- No fence is in progress in the pipeline.
我不知道这是什么意思。参见:https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/805373.
- Not many other load misses are in progress.
只有 10 个填充缓冲区可以容纳错过 L1D 的请求。这提出了一个问题,如果只有一个可用的填充缓冲区,硬件预取器会使用它还是将其留给预期的需求访问?我不知道。
- There is not a continuous stream of stores.
这表明如果有大量商店与少量负载交织在一起,L1 预取器将忽略负载并基本上暂时关闭,直到商店成为少数。然而,我的实验结果表明,即使是单个存储到页面也会关闭该页面的预取器。
所有英特尔凌动微架构都具有 DCU 预取器。尽管预取器可能会跟踪这些微体系结构中少于 4 个页面。
包括 Knights Landing 在内的所有 Xeon Phi 微体系结构都没有 DCU 预取器。我不知道以后的 Xeon Phi 微架构。