Files
LDD-LinuxDeviceDrivers/study/arch/topdown
2021-11-06 22:18:07 +08:00
..
2021-10-24 22:19:20 +08:00
2021-10-24 22:19:20 +08:00
2021-10-24 22:19:20 +08:00
2021-11-06 22:18:07 +08:00
2021-10-27 23:28:58 +08:00
2021-10-27 23:37:08 +08:00

title, date, author, tags, categories, thumbnail, blogexcerpt
title date author tags categories thumbnail blogexcerpt
工具 2021-06-26 09:40 gatieme
linux
tools
技术积累
虚拟化 & KVM 子系统

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作

知识共享许可协议

因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 鄙人在此谢谢啦

转载请务必注明出处, 谢谢, 不胜感激


日期 作者 GitHub CSDN BLOG
2021-02-15 成坚-gatieme AderXCoding/system/tools/fzf 使用模糊搜索神器 FZF 来提升办公体验 Using FZF to Improve Productivit

1 Top-Down 概述


自顶向下的微架构分析方法(Top-Down Microarchitecture)

2 背景知识解析


2.1 流水线


2.1.1 流水线的 topdown 划分


类型 描述
Front-End/前端 负责获取程序代码指令, 并将其解码为一个或者多个微操作(uOps), 这些 uOps 将分配给 Back-End 去执行.
Front-end 负责交付 uOps 给 Back-end 执行. Front-end 从 Icache 中提取代码字节流到流水线, 通过分支预测器预测下一个地址以进行提取. 将代码字节分割成指令, 并发送给解码器, 解码器将指令解码到 uOps(mirco-ops), 以便交给 Back-end 执行.
Back-end/后端 负责监控 uOps 的数据何时可用, 并将其安排到可用的执行单元中执行.
Speculation/预测 部分跳转指令可能需要对跳转方向和跳转地址进行预测. 通常情况下, 大多数 uOps 都会通过流水线并正常退役, 但是在预测错误的情况下, 投机执行的 uOps 可能会在退役前被取消并从流水线中清楚掉.
Retirement/退役 uOps 执行完成. 这被称为退役

2.1.2 流水线各个阶段


编号 过程 描述 是否乱序
1 取指(fetch) 从 Icache 中取出多条指令, 在取指阶段, 除了需要取出多条指令, 同时还需决定下个周期的取指地址, 因此一般会由分支预测器来决定下一条指令的PC, 再从 I-cache 中取指. In Program Order
2 译码(decode) 识别指令类型、操作数及控制信号, 将指令翻译成一条或者多条硬件可直接处理的 uOps In Program Order
3 寄存器重命名 寄存器重命名使得处理器可调度更多指令并行执行, 通过表格存储ARF和PRF的映射关系、未使用的PRF等信息, 分析并标记RAW相关性的指令, 一般会把该步骤单独放一流水段 In Program Order
:---: :---: :----:
4 分发(dispatch) 被重命名后的指令顺序写入发射队列、ROB和SB中, 如果没有空间则需要在重命名阶段等待, 分发可和重命名放一个流水段, 也可分开 In Program Order
5 发射(issue) 仲裁(select)电路从发射队列中选择准备好的最合适的指令送进FU执行, 发射队列中还存在唤醒电路, 将队列中对应的源操作数置为有效, 仲裁电路和唤醒电路配合工作, 是处理器中的关键路径; In Program Order
6 读取寄存器(register read) 被仲裁电路选中的指令从PRF或旁路网络中得到操作数, 旁路网络的存在使得减少PRF读端口成为可能, 多端口寄存器堆访问速度慢, 需要单独使用一个流水段; In Program Order
7 执行(execute) 得到操作数后送入对应 FU 中执行, 一般包括负责普通运算、乘累加运算、分支指令运算、load/store指令运算等FU, 现代处理器还会加入负责多媒体运算如进行单指令多数据(SIMD)运算的FU. 一般各个执行单元有各自的 issue queue, 执行 uOps. Out Of Order
8 写回(write back) 将计算结果顺序写入 PRF, 还需要通过电路网络送出, 该电路布线非常重要直接影响速度, 一般使用cluster结构将FU分组, 同组FU紧挨, 可在一个周期送出, 跨组则需更多周期 In Program Order
9 提交(commit) ROB 顺序将结果写入 ARF, 同时处理异常, 所有异常均需到达该阶段后再进行处理以实现精确异常, 指令从ROB离开后无法再修改处理器状态. In Program Order

2.2 uOps 与 Pipeline Slots


类型 描述
uOps micro-ops/micro-operations/微指令 是一种底层硬件操作, CPU 前端负责获取体系结构指令中表示的程序代码, 并将其解码为一个或多个 uops.
Pipeline Slots Pipeline Slot(流水线槽) 代表着一个 uOps 所需的硬件资源. Top-Down 分析方法假定对于每个 CPU 核, 在每个时钟周期, 有多个可用的 Pipeline Slots. 这些 Pipeline Slots 的数量被称为 Pipeline Width.

2.2.1 Pipeline Slots


在下图的示例中, 是用 4-wide(4-way) 的 CPU 将代码执行 10个时钟周期.

Pipeline Slots 的示例 1

在这个示例中, 包含了 40 个 Pipeline Slots(4 * 10) 资源. 如果一个 Pipeline Slot 没有 retire, 则认为有一个 uOp 产生阻塞(Stall).

如下图所示, 有 20 个 slots(红色) 产生阻塞(没有使一个 uOp 达到 Retire). 这表示从该微架构的角度来看, 代码的执行效率只有 50%.

Pipeline Slots 的示例 2

以 Pipeline Slots 为基础资源所观测和统计到的 Top-Down 数据(如 Front-End Bound 和 Back-End Bound 等), 则表示因各种原因(如 Front-End 问题和 Back-End 问题)导致的 Pipeline Slots 阻塞占总体的百分比.

2.2.2 为什么以 Pipeline Slots 为粒度统计


我们统计 top-down 数据是以 Pipeline Slots 为基准的, 而没有采用 cycle(Clockticks) 作为基准. 理论上将我们统计每个周期内阻塞的占比岂不是更有意义 ?

我们同样用一个示例来看下这个疑问 ?

Pipeline Slots 的示例 2

在这里, 每个周期有两个 Pipeline Slots 被阻塞, 也就是 50% 的 Stalls 和 50% 的 Retiring. 如果使用 Clockticks 而言, 却认为是 100% 的 Stalls, 因为每个周期(cycle)都有一些 Pipeline Slots 被占用.

可见, 与以 Pipeline Slots 测量的指标相比, 以 Clockticks 测量的指标不太精确. 但是, 此类指标对于识别代码中的主要性能瓶颈仍然很有用.

3 topdown 模型层级划分


类型 描述
Front-End Bound/前端阻塞 表示 pileline 不足以供应 Back-end. 也就是说当 Back-end 准备接收 uOps 时, Pipeline Slots 出现了 stall. Front-End Bound 可以进一步分为:
1. Fetch Latency Bound: 无法从 Icache 获取指令导致的阻塞, 如 icache/itlb miss 以及 branch resteers(sp flush) 等
2. Fetch Bandwidth Bound: 指令的传输带宽不足, 有多余的指令等待接收, 如 sub-optimal decoding.
Back-end Bound/后端阻塞 表示由于缺乏 uOps 执行所需的后端资源造成的停顿. 它可以进一步细分为:
1. Memory Bound: 由于 cache 以及 memory 子系统无法及时提供(准备好) uOps 执行所需数据造成的停顿卡顿.
2. Core Bound: 执行单元压力 Compute Bound 或者去缺少指令集并行 LTP. 一般意味着计算单元或者指令级别并行度的缺失, 大量指令长期使用相同的计算单元
3. Resource Bound: OOO(Out Of Order) 阶段的阻塞, 比如物理寄存器(PRF)或者 ROB 不足.
Bad Speculation/投机错误 由于分支预测错误导致的 Pipeline Slot 被浪费. 主要包括 Front-End 最终被取消的 uOps 的 pipeline Slots, 以及 Back End 过程中由于从先前错误的猜测中恢复而阻塞造成的 Pipeline Slot.
Retring/正常执行 表示运行有效的 PileSlots.

理想情况下, 我们希望所有看到的 Pileline Slot 都归类到 Retring. 因为他与 IPC 息息相关.

在每个 CPU 周期中, pipeline slot 可以是空的或者被 uOp 填充. 如果在一个 CPU 周期内某个 pipeline slot 是空的, 称之为一次停顿(stall). 如果 CPU 经常停顿, 系统性能肯定是受到影响的. TMAM 的目标就是确定系统性能问题的主要瓶颈.

topdown 划分

  • 如果一个 Pipeline Slot 被某个 uOps 占用, 它将被分类到 Retring 或者 Bad Speculation, 具体取决于他是否被提交(commit).

  • 如果 Pipeline 中某个 Back-end 阶段 Pipeline Slot 都被占用, 导致后续流程无法接受更多的操作. 则未被利用的 Pileline Slot 就被归类为 Back-end Bound.

  • 同样出现 Front-End Bound 则表示在没有 Back-end Stall 的情况下, 没有更多的 uOps 被分配(allocate)给 Back-end(后端)去处理.

在目前比较常见的 Intel X86_64 的微架构实现上, 流水线的 Front-end 每个 cycle 可以分配 4 个 uOps, 同样 Back-end 也可以在每个 cycle 中退役 4 个 uOps.

于是 TMAM 假定对于每个 CPU 核, 在每个 cycle, 均有 4 个 Pipeline Slot 可用, 然后使用一些自定义的 PMU 事件来测量这些 pipeline slot 的使用情况.

但是请注意:

通常来说 CPU 每个 cycles 最多可以处理 4 个 uOps, 用 topdown 简单的表示为每个 cycles 最多有 N 个 Pipeline Slots 可用, 但是通常这并简简单单是 CPU 某个阶段(fetch/dispatch/issue/execute)的处理能力, 而是指整个流水线整体的最小处理能力. 类比知乎上经典问题 如何判断CPU发射宽度?.

3.1 Front-End Bound/前端阻塞


3.2 Back-end Bound/后端阻塞


3.3 Bad Speculation/投机错误


3.4 Retring/正常执行


1 参考资料


编号 链接 描述
1 A Journey Through the CPU Pipeline 讲述了 CPU 流水线的前世今生(不断演进和完善), 翻译版本
2 Top-down Microarchitecture Analysis Method
3 A Top-Down method for performance analysis and counters architecture Intel 关于 topdown 分析方法的论文, 以及 slide
4 Intel P4 CPU
5 The Berkeley Out-of-Order Machine (BOOM)
6 Top-down Microarchitecture Analysis through Linux perf and toplev tools