Skip to content

AMD Zen 架构微架构深度分析 Session 总结

1. AMD Zen 6 前端传闻与架构演进 (Frontend Evolution)

Q: 网传 Zen 6 将调整至 8 宽发射,这意味着前端需要极高的带宽。如何理解 AMD 的解耦前端、FTB 以及单周期 2 Taken 分支预测?

A. 核心技术解析

AMD 的高发射宽度依赖于其 解耦前端 (Decoupled Frontend) 设计。

  • 解耦机制 (OpCache):
    • AMD 从初代 Zen 开始引入 OpCache (Micro-op Cache)。指令解码后存入 OpCache,后续 Fetch 直接从 OpCache 取微码,绕过瓶颈巨大的 Legacy x86 Decoder。
    • Zen 4/5 的 OpCache 带宽极高(单周期 8+ uops),是支撑后端“饥饿”的关键。
  • 分支预测 (Branch Prediction):
    • FTB (Fetch Target Buffer): 虽然 AMD 常用 L1/L2 BTB 术语,但其原理与学术界的 FTB 类似。Zen 3/4 引入了 "Zero-Bubble" 能力。
    • 2 Taken Branches: Zen 5 被传闻在 Fetch 阶段采用了双路解码/预测设计,能够在一个周期内处理非连续的指令流(即预测并跳转两次),这对应了学术界的高吞吐 FTB 概念。
    • 算法: 基于 TAGE 和 Hashed Perceptron(神经网络感知器)的混合预测。

推荐资源:

  • Chips and Cheese: "Zen 4 Frontend Analysis", "Deep Dive into Zen 5".
  • Hot Chips 会议: Mike Clark 关于 Zen 架构的 PPT。
  • Agner Fog: Microarchitecture Manual.

2. 向量执行引擎与 Non-Scheduling Queue (NSQ)

Q: 在 Chips and Cheese 关于 Zen 4 的分析中,提到向量部分有一个 "Non-Scheduling Queue" (NSQ),且调度逻辑与标量不同。这是什么意思?

A. 调度架构对比

  • 整数 (Integer): 分布式调度
    • 重命名 (Rename) -> 直接进入各个端口专属的小调度器 (Scheduler)。
    • 流程短,速度快。
  • 向量/浮点 (Vector/FP): 两级调度结构
    • 结构: 重命名 -> NSQ (缓冲队列) -> Scheduler (统一调度站)。
    • NSQ 的作用: 它是一个“候机厅”。指令在这里排队,不参与昂贵的操作数唤醒扫描,仅做 FIFO 缓冲。只有当 Scheduler 有空位时,指令才从 NSQ 移动到 Scheduler。
    • 目的: 人为撑大“在途指令窗口”,掩盖延迟,同时不增加高功耗 Scheduler 的面积。

3. 资源分配变革:Zen 4 vs. Zen 5 (Late Allocation)

Q: Zen 5 将重命名移到了 NSQ 之后(Late Allocation),不占用物理寄存器。这是怎么实现的?为什么“不让进调度器傻等”不会变成顺序执行?为什么浮点也要进 NSQ?

A1. 晚期分配 (Late Allocation / PRF Virtualization)

  • Zen 4 (Early Allocation): 指令在 Decode/Rename 阶段就分配了昂贵的 512-bit 物理寄存器 (PRF)。如果在 NSQ 排队,这个 PRF 就被“占着茅坑不拉屎”,导致 PRF 耗尽,前端 Stall。
  • Zen 5 (Late Allocation):
    • Rename 阶段: 只分配一个 Tag (标签),不分配实际的数据存储空间 (Payload RAM)。
    • NSQ 阶段: 指令带着 Tag 排队,极度轻量。
    • Dispatch 阶段: 指令即将进入 Scheduler 执行时,才真正从 Free List 划拨物理寄存器空间。
    • 收益: 指令窗口不再受限于物理寄存器数量 (e.g., 200),而是受限于重命名表大小 (e.g., 400+),极大提升了掩盖内存延迟的能力。

A2. 关于“顺序”与“傻等”的误解

  • NSQ -> Scheduler: 确实是按序流入。
  • Scheduler 内部: 是完全乱序的。
  • 哲学: Scheduler 是昂贵的 VIP 房(高功耗 Wakeup Logic)。让未就绪的指令在普通的 NSQ 里等,保证 Scheduler 里都是“大概率能马上执行”的指令,这提高了执行效率和能效,并没有牺牲乱序能力。

A3. 为什么浮点/向量必须进 NSQ?

  1. 共享资源: 标量浮点 (Scalar FP) 和 SIMD 向量共享同一个物理寄存器堆 (VRF) 和数据通路,无法拆分。
  2. 调度效率: FP/Vector 指令延迟长,若无限制涌入,会迅速填满 Scheduler,阻塞流水线。
  3. 功耗: 减少高位宽指令在 Wakeup 逻辑中的翻转率。

4. 指令窗口、uop 拆分与投机调度

Q: “盖住的延时”是谁的延时?向量/浮点会被拆成一个 uop 吗?写回和提交逻辑是什么?有投机调度吗?

A. 细节解析

  • 盖住的延时: 主要是 内存 (DRAM) 延时。通过 Late Allocation 扩大窗口,即使头部指令 Cache Miss 卡住 500 周期,CPU 也能继续吃进后续几百条不相关的指令进行乱序执行。
  • uop 拆分:
    • Zen 4: 512-bit 指令可能拆分为 2 个 256-bit 操作 (Double-pumped)。
    • Zen 5: 原生 512-bit 数据通路,512-bit 指令通常是 1 个 uop
  • 写回 (Write-back) vs. 提交 (Commit):
    • 写回: 乱序发生。计算完立刻广播 CDB,写入 PRF,唤醒依赖指令。
    • 提交: 顺序发生 (由 ROB 负责)。确保精确异常 (Precise Exception)。
  • 投机调度 (Speculation):
    • 确定性延迟投机: 假设 ALU 指令会在 N 周期后完成,提前唤醒依赖指令。
    • Load-to-Use 投机: 向量 Load 即使没回数据,调度器也会赌它是 L1 Hit,提前发射依赖它的 VADD。如果赌输了 (L1 Miss),则触发 Replay (重播) 机制,撤回并重新发射。

5. 向量访存难点:Mem-Order Violation & Forwarding

Q: 向量上的 Memory Order Violation 和 Store-to-Load Forwarding (STLF) 怎么做?是逐地址检查吗?

A. LSU 的粗粒度检查与保守策略

1. Mem-Order Violation (内存序冲突检测)

  • 机制: 绝不进行逐字节 (Byte-level) 检查,太昂贵。
  • 方法: 区间重叠 (Range Overlap)Cache Line 粒度 检查。
    • 检查 [Store_Start, Store_End][Load_Start, Load_End] 是否有交集。
  • MDP (Memory Dependence Predictor): 用于预测某条 Load 是否经常与 Store 冲突。如果预测冲突,强制让 Load 在调度阶段等待 Store 解析地址。

2. Store-to-Load Forwarding (STLF)

向量转发是 LSU 设计的噩梦,遵循“能不转就不转”的原则。

  • 完美转发 (Exact Match): Store 与 Load 地址、大小完全一致。 -> 成功 (Fast Path)。
  • 子集转发 (Subset): Load 包含在 Store 范围内且对齐良好。 -> 成功。
  • 错位/部分重叠 (Misaligned/Partial):
    • 例如:Store 写入 0x00-0x40,Load 读取 0x08-0x48(错位)。
    • 结果: STLF Failure (转发失败)。
    • 处理: 硬件放弃转发,Load 指令被 Flush/Replay。Load 必须等待 Store 数据完全写入 L1 Cache 后,再从 Cache 读取拼接好的数据。这会带来巨大的延迟惩罚。
  • Masked Store: 带有写掩码的 Store 通常不支持转发,因为涉及旧值合并。

总结: 向量代码优化极其依赖数据对齐和访问模式,以避免昂贵的 Replay 和 STLF Failure。

AI 生成的。