【发布时间】:2019-12-21 17:06:01
【问题描述】:
我正在学习 CPU 和管道。我们知道在处理器流水线执行阶段存在一些负载存储单元。
现在我想知道,如果我们有一个加载指令需要很长时间,因为请求的数据在缓存中不存在,除非我们有另一个加载,否则下一个加载指令将不会执行,直到第一个加载解决了乱序 cpu /store 单元在管道执行阶段?
有序 CPU 的相应行为是什么?
【问题讨论】:
标签: arm cpu-architecture cpu-cache cortex-a8
我正在学习 CPU 和管道。我们知道在处理器流水线执行阶段存在一些负载存储单元。
现在我想知道,如果我们有一个加载指令需要很长时间,因为请求的数据在缓存中不存在,除非我们有另一个加载,否则下一个加载指令将不会执行,直到第一个加载解决了乱序 cpu /store 单元在管道执行阶段?
有序 CPU 的相应行为是什么?
【问题讨论】:
标签: arm cpu-architecture cpu-cache cortex-a8
稍后会加载缓存未命中的加载块吗?可以设计 CPU 来避免它。
您要查找的术语是 hit under miss 表示在等待未完成的缓存未命中时进行缓存访问,miss under miss 表示存在多个未完成的缓存未命中(内存级并行)。
请参阅https://www.ece.ucsb.edu/~strukov/ece154BSpring2018/week3.pdf 了解非阻塞缓存和流水线缓存。
在无序 CPU 中,这可以通过暂时给出加载指令并稍后从调度程序再次重播来处理。至少,英特尔 x86 CPU 就是这样做的。像 ARM 这样具有弱排序内存模型的 CPU 可能只需要一个加载缓冲区来等待该高速缓存行到达 L1d 高速缓存,而无需重新运行加载指令。
在有序流水线中,加载可以是scoreboarded,因此在您尝试实际读取由缓存未命中加载写入的寄存器之前,不会发生任何停顿。您需要一些加载缓冲区来等待传入的缓存行,但随后命中未命中和未命中未命中即可工作。
(Paul Clayton 在https://electronics.stackexchange.com/questions/98551/what-happens-on-a-cache-miss 上发布了一个更详细的答案)
请记住,按顺序仅意味着指令必须开始按程序顺序执行。高延迟指令(例如除法,尤其是存储和加载)可能会乱序完成。即使是缓存 hit 存储在现代高速有序设计上也有足够的延迟,您希望让其他指令在该延迟的阴影下运行。
管道的不同复杂度级别可能支持也可能不支持 hit-under-miss 和/或 miss-under-miss。即不同数量的 MLP(Memory Level Parallelism)。
乱序 CPU 几乎总是支持两者; OoO exec 的主要优点之一是隐藏内存延迟以及 ALU 延迟。
Cortex-A8's glossary 提到 Hit Under Miss,但在 IDK 中,他们实际上使用该术语来明确表示 A8 是否支持它。
我确实找到了16.4.2. Memory system effects on instruction timings,上面写着:
由于处理器是静态调度设计,内存系统的任何停顿都可能导致最少 8 个周期的延迟。这个 8 周期的最小延迟与在 L1 加载未命中的情况下从 L2 高速缓存接收数据的最小可能周期数相平衡。表 16.16 给出了可能由于内存系统停顿而导致指令重放的最常见情况。
条件列表包括 L1 加载数据未命中。随后的 L2 未命中可能会导致再次重播,从而将后面的指令再延迟 8 个周期。
这听起来确实像 A8 确实不支持缓存未命中的任何内容,而是基本上停止。
【讨论】:
PLD 或预加载,它对地址进行缓存加载;如果地址是 L1 或 L2 命中或 TLB 未命中(需要进行页面遍历以查看它是否可缓存),则它什么也不做。因此,如果您有一些有序的访问,您可以使用PLD 来确保数据在缓存中可用并避免停顿。
PLD,因为它知道访问模式。通常只有 L2 大小需要填充。通常从 L2 到 L1 的传输并没有那么糟糕,添加许多 PLD 来填充 L1 会污染指令流。 cortex-A8 是最早的 ARMv7a CPU 之一。它不太可能具有任何 MLP 功能。如果东西插在墙上,你可以疯狂地烧电。 ARM 尽量不这样做。 Gcc 甚至不会为 cortex-A8 发出 PLD,但会为 cortex-a9 发出;程序员可以手动插入。