gpt4 book ai didi

performance - 预取指令是否需要在退出之前返回其结果?

转载 作者:行者123 更新时间:2023-12-04 15:06:25 26 4
gpt4 key购买 nike

在最近的 Intel 和 AMD CPU 上,已执行但所请求的行尚未到达指定缓存级别的预取指令是否仍然可以退出?

也就是说,预取“阻塞”的退休是因为它似乎是用于加载,还是非阻塞?

最佳答案

关于英特尔处理器,没有。这在 Intel 优化手册第 7.3.3 节中提到:

PREFETCH can provide greater performance than preloading because:

  • Has no destination register, it only updates cache lines.
  • Does not complete its own execution if that would cause a fault.
  • Does not stall the normal instruction retirement.
  • Does not affect the functional behavior of the program.
  • Has no cache line split accesses.
  • Does not cause exceptions except when the LOCK prefix is used. The LOCK prefix is not a valid prefix for use with PREFETCH.
  • Does not complete its own execution if that would cause a fault.

The advantages of PREFETCH over preloading instructions are processor specific. This may change in the future.



另外第 3.7.1 节说:

Software PREFETCH operations work the same way as do load from memory operations, with the following exceptions:

  • Software PREFETCH instructions retire after virtual to physical address translation is completed.
  • If an exception, such as page fault, is required to prefetch the data, then the software prefetch instruction retires without prefetching data.


我已经在 Haswell 和 Broadwell 上通过实验验证了这两点。

enter image description here

enter image description here

所有未命中 TLB:所有预取指令都未命中所有 MMU 和数据缓存,但页面在主内存中(没有次要或主要页面错误)。

All hit TLB:所有预取指令都命中 L1 TLB 和数据缓存。

不同页面出错:所有预取指令都未命中所有 MMU 和数据缓存,页面描述符导致页面错误。每个预取指令访问不同的虚拟页面。

同一页错误:所有预取指令都未命中所有 MMU 和数据缓存,并且页描述符导致页错误。每个预取指令访问相同的虚拟页面。

对于 Broadwell 图,结果 PREFETCH0PREFETCHW显示。 PREFETCHW Haswell 不支持。 Haswell 和 Broadwell 上的频率分别固定为 3.4GHz 和 1.7GHz,我在两者上都使用了 intel_pstate 功率缩放驱动程序。所有硬件预取器都已打开。注意 PREFETCHW的延迟页错误与目标页是否可写无关。只读页导致的故障与由于任何其他原因导致的故障具有相同的影响。此外,我的实验仅考虑没有内核具有缓存行副本的情况。

由于 1c 依赖链,预计 1 个周期的吞吐量:
loop:
prefetcht0 (%rax)
add $0x1000,%rax
cmp %rbx,%rax
jne loop

在 Broadwell 上,“故障相同页面”情况似乎比“故障不同页面”情况稍慢。这与哈斯韦尔相反。我不知道为什么。这可能取决于包含无效条目的分页结构的级别,页面遍历器基本上在该级别检测到页面错误。这取决于操作系统。

我认为预取指令不能在 TLB 未命中时立即退出的原因是因为加载单元没有像存储单元那样的退出后逻辑。这里的想法是,由于很可能会在预取之后对页面进行需求访问(这可能是预取的原因),因此无论如何在需求访问或预取中都会由于 TLB 未命中而导致停顿。尤其是当紧跟在预取之后的指令不访问同一页面时,暂停预取会更好。

此外, 我已经通过实验验证预取指令可以在预取操作完成之前退出 通过放置 LFENCE在预取指令之后,并观察到与使用加载而不是预取相比,每个预取指令的时间仅略有增加(栅栏的成本)。

Xeon Phi 处理器上的软件预取指令的执行方式与 Haswell/Broadwell 1 上的执行方式相同,但另请阅读下面有关 Itanium 的部分。

第 7.3.3 节还说:

There are cases where a PREFETCH will not perform the data prefetch. These include:

  • In older microarchitectures, PREFETCH causing a Data Translation Lookaside Buffer (DTLB) miss would be dropped. In processors based on Nehalem, Westmere, Sandy Bridge, and newer microarchitectures, Intel Core 2 processors, and Intel Atom processors, PREFETCH causing a DTLB miss can be fetched across a page boundary.
  • An access to the specified address that causes a fault/exception.
  • PREFETCH targets an uncacheable memory region (for example, USWC and UC).
  • If the memory subsystem runs out of request buffers between the first-level cache and the second-level cache.
  • The LOCK prefix is used. This causes an invalid opcode exception.


第二点已经在 Haswell、Broadwell 和 Skylake 上进行了实验验证。我的代码无法检测到当 LFB 用完时可以丢弃状态预取请求的第四点。 AMD results似乎表明 AMD 也放弃了预取请求。但是在 AMD 上的每次访问时间仍然比在 Intel 上小得多。我认为 AMD 会在 TLB 填充缓冲区已满时丢弃预取请求,而英特尔会在 L1D 填充缓冲区已满时丢弃它们。我的代码永远不会使 L1D 填充缓冲区满,这解释了 AMD 与 Intel 的结果。

第一点说,在 Core2 和 Atom 微体系结构及更高版本上,软件预取不会因 TLB 未命中而丢失。根据旧版本的优化手册,型号为 3 或更大的奔腾 4 处理器也不会在 TLB 未命中时丢弃软件预取。英特尔酷睿微体系结构和(某些)奔腾 M 处理器也可能是这种情况(我无法找到有关这些处理器的英特尔来源)。型号小于 3 的奔腾 III 处理器和奔腾 4 处理器肯定会在 TLB 未命中时放弃软件预取。 Pentium III 之前的处理器不支持软件预取指令。

预取 uops 被分派(dispatch)到端口 2 或 3 并在加载缓冲区中分配。对同一缓存行的预取 uops 不会合并。也就是说,每个 uop 将获得自己的加载缓冲区。我认为(但我没有通过实验验证)ROB 条目是为预取 uops 分配的。只是 ROB 永远不会在预取 uops 上停顿,只要它们已被分派(dispatch)到加载端口。

与常规加载不同,预取请求本身(发送到 L1d 或缓存的外部级别)不是预取 uop 在 ROB 中标记为完成并准备退出之前必须等待的。

有一个有趣的2011 patent讨论了对 Itanium2 处理器上软件预取的增强。它提到以前的安腾处理器在软件预取错过 TLB 时不得不停顿,因为它们被设计为不丢弃任何软件预取请求,后来的指令无法通过它,因为它们是有序处理器。该专利提出了一种设计,允许软件预取请求相对于后续指令乱序执行而不会丢弃它们。这是通过添加一个数据预取队列 (DPQ) 来完成的,该队列用于排列未命中 TLB 的软件预取请求。然后在硬件页表遍历完成后重新发出 DPQ 中的预取。此外,添加了多个硬件页表遍历器以潜在地允许以后的请求访问执行,即使它们错过了 TLB。但是,如果 DPQ 用预取指令填满,流水线将在下一条预取指令上停顿。此外,根据该专利,即使出现页面错误,也不会丢弃软件预取请求。这与大内核和至强融核形成对比。该专利还讨论了在 Itanium 中实现的硬件预取器。

在乱序的大核微架构中,负载缓冲器自然而然地扮演了DPQ的角色。不知道Xeon Phi有没有这样的结构。

AMD 优化手册第 5.6 节说如下:

The prefetch instructions can be affected by false dependencies on stores. If there is a store to an address that matches a request, that request (the prefetch instruction) may be blocked until the store is written to the cache. Therefore, code should prefetch data that is located at least 64 bytes away from any surrounding store’s data address.



我很好奇通过放置两条预取指令和一条存储指令(后跟一个虚拟的 add rax, rax )在英特尔处理器(在 Haswell 上)上进行测试,我观察到以下情况:
  • UOPS_RETIRED.STALL_CYCLES明显大于核心周期数,这是没有意义的。
  • 发送到端口 2 和 3 的 uops 总数比预期的高出约 16%。这表明正在重放预取 uops。
  • RESOURCE_STALLS.ANY报道基本没有摊位。这与有两个预取指令后跟两个虚拟 ALU 指令(流水线在加载缓冲区上停顿)的情况形成对比。

  • 但是,只有当存储与预取指令相同的 4K 页时,我才观察到这些影响。如果商店位于不同的页面,则代码的工作方式与带有两个虚拟 ALU 的代码类似。因此,存储似乎与英特尔处理器上的预取指令进行交互。

    (1) 但它们与硬件预取器的交互方式不同。然而,这是退休后的影响。

    (2) Itanium 是 IA-64 处理器系列,因此它与问题并不完全相关。

    关于performance - 预取指令是否需要在退出之前返回其结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52377191/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com