一个简单的 5 级处理器的级需要多少个时钟周期?

问题描述

5 级流水线 cpu 具有以下阶段序列:

  • IF – 从指令存储器中提取指令。

  • RD – 指令解码和寄存器读取。

  • EX – 执行:数据和地址计算的 ALU 操作。

  • MA – 数据存储器访问 – 对于写访问,在 RD 状态下读取的寄存器为 用过。

  • WB – 寄存器回写。

现在我知道,例如,从内存中获取指令可能需要 4 个周期(L1 缓存)或最多约 150 个周期(RAM)。但是,在每个流水线图中,我都会看到类似 this内容,其中每个阶段都分配了一个周期。

现在,我当然知道真正的处理器具有超过 19 个阶段的复杂管道,并且每个架构都不同。但是,我在这里错过了什么吗? IF 和 MA 中的内存访问,这个 5 级流水线是否需要几十个周期?

解决方法

Classic 5-stage RISC pipelines 是围绕单周期延迟 L1d / L1i 设计的,允许代码中有 1 个 IPC(每时钟指令),而不会出现缓存未命中或其他停顿。即希望常见/好的案例。

当时的时钟速度较低(甚至相对于 1 个门延迟),因此您可以在一个周期内完成更多工作,并且缓存更简单,通常为 8k 直接映射、单端口,有时甚至是虚拟标记 (VIVT)所以 TLB 查找不是访问延迟的一部分。

(与 modern Intel/AMD using 32kiB 8-way VIPT L1d/L1i caches 相比,L1d 至少有 2 个读取 + 1 个写入端口,时钟速度如此之高以至于访问延迟 4 cycles best-case on Intel SnB-family,or 5 cycles including address-generation。现代 CPU 具有更大的TLB 也是如此,这也会增加延迟。当乱序执行和/或其他技术通常可以隐藏延迟时,这是可以的,但是经典的 5 阶段 RISC 只有一个管道,而不是单独的管道内存访问。有关现代超标量乱序 exec x86 CPU 与经典 RISC CPU 的性能有何不同的更多链接,另请参阅 Cycles/cost for L1 Cache hit vs. Register on x86?。)

如果您想为相同的晶体管性能(门延迟)提高时钟速度,您可以将 fetch 和 mem 阶段分成多个流水线阶段(即更大量地流水线化它们),如果缓存访问甚至在关键路径上(即如果缓存访问不能再在一个时钟周期内完成)。延长流水线的缺点是增加了分支延迟(错误预测的成本,以及正确预测必须隐藏的延迟量),以及增加总晶体管成本。


请注意,经典 RISC 流水线在 EX 阶段进行地址生成,使用那里的 ALU 计算寄存器 + 立即数,这是大多数 RISC ISA 支持的唯一寻址模式,围绕此类流水线构建。因此,由于转发回 EX 的负载延迟,因此负载使用延迟实际上是指针追逐的 2 个周期。)


如果缓存未命中整个管道就会停止:那些早期的管道缺少 store buffer 来将执行与存储未命中,或从 L1d 缓存加载的未命中/未命中/未命中。

还请记住,对于 MIPS R2000 等早期 CPU,CPU 速度相对于内存而言并不高,而且单核机器不需要内核和内存控制器之间的互连。 (虽然他们可能确实有一个前端总线到一个单独的芯片上的内存控制器,一个“北桥”。)但无论如何,在那个时候,对 DRAM 的缓存未命中花费的核心时钟周期要少得多。在每次未命中时完全停顿很糟糕,但它不像现代 CPU 那样可以在 150 到 350 个周期范围内(70 ns * 5 GHz)。 DRAM 延迟几乎没有像带宽和 CPU 时钟那样改善。另请参阅具有“内存墙”部分的 http://www.lighterra.com/papers/modernmicroprocessors/,以及 Why is the size of L1 cache smaller than that of the L2 cache in most of the processors? 回复:为什么现代 CPU 需要多级缓存,因为 CPU 速度和内存延迟之间的不匹配已经加剧。

后来的 CPU 通过允许在无故障加载(成功 TLB 查找)后继续执行等操作,允许逐渐增加内存级并行性,仅在您实际读取最后一个寄存器时停止如果加载结果尚未准备好,则由加载写入。这允许在仍然很短且相当简单的有序管道上隐藏加载延迟,并使用一定数量的加载缓冲区来跟踪未完成的加载。通过寄存器重命名 + OoO exec,ROB 大小基本上是您可以隐藏缓存未命中延迟的“窗口”:https://blog.stuffedcow.net/2013/05/measuring-rob-capacity/

现代 x86 CPU 甚至在前端的流水线阶段之间有缓冲区来隐藏或部分吸收提取气泡(由 L1i 未命中、解码停顿、低密度代码引起,例如跳转到另一个跳转,甚至只是未能预测一个简单的始终采用的分支。即只有在它最终被解码时才检测它,在获取正确路径以外的东西之后。没错,即使是像 jmp foo need some prediction 这样的无条件分支用于获取阶段。)

https://www.realworldtech.com/haswell-cpu/2/ 有一些很好的图表。当然,Intel SnB 系列和 AMD Zen 系列使用解码 uop 缓存,因为 x86 机器代码难以并行解码,因此它们通常可以绕过一些前端复杂性,有效缩短管道。