AMD GPU性能诊断指南:五步构建指令屋顶线模型
核心概念:什么是指令屋顶线模型?
想象一下,你要评估一辆跑车的极限性能。你会关心两个核心指标:发动机的最高时速(计算性能)和轮胎的抓地力(内存带宽)。
指令屋顶线模型就是这个思路在GPU性能分析上的应用:
- 计算天花板:你的AMD GPU一秒钟最多能执行多少十亿条指令(GIPS)。这就像发动机的极限速度。
- 内存带宽天花板:你的AMD GPU一秒钟最多能从内存中搬运多少千兆字节的数据(GB/s)。这就像轮胎的极限抓地力。
通过这个模型,我们可以快速判断一个程序(比如科学模拟、AI模型)在特定GPU上是"计算瓶颈"(发动机没劲)还是"内存瓶颈"(轮胎打滑),从而进行针对性优化。
准备工作:你的"工具箱"清单
在开始动手之前,请确保你准备好了以下工具和环境:
- AMD GPU:一块支持ROCm的AMD显卡,例如本教程主要涉及的 Radeon Instinct MI60 或 Instinct MI100。
- ROCm平台:安装好AMD的ROCm(Radeon Open Compute)软件平台。这是运行和性能分析的基础。
- 性能分析工具:AMD ROCProfiler (`rocProf`)。它通常包含在ROCm安装包中,用于收集GPU内部的各项性能指标。
- 基准测试工具:BabelStream(HIP实现版)。我们将用它来测量你GPU的极限内存带宽。
- 目标应用程序:一个你希望分析其性能的程序。我们将以开源等离子体模拟软件PIConGPU为例。
步骤详解:五步构建你的指令屋顶线模型
步骤一:使用ROCProfiler收集核心指标
首先,我们需要让 `rocProf` 工具帮我们"读取"GPU运行程序时的"仪表盘"数据。
- 关键操作:在终端中,使用 `rocProf` 运行你的目标程序(例如PIConGPU的某个模拟内核)。你需要特别关注并收集以下四个核心指标:
- `SQ_INSTS_VALU`: 向量算术逻辑单元指令数。
- `SQ_INSTS_SALU`: 标量算术逻辑单元指令数。
- `FETCH_SIZE`: 从GPU内存中读取的数据总量(单位:KB)。
- `WRITE_SIZE`: 向GPU内存中写入的数据总量(单位:KB)。
- 同时,记录下内核的 `运行时间`。
避坑指南:
- 务必注意单位转换! `FETCH_SIZE` 和 `WRITE_SIZE` 给出的单位是KB,在后续计算中我们需要统一转换为字节(Byte)。
- 确保你的ROCm版本与GPU型号兼容,否则可能无法正确读取这些指标。
步骤二:计算总指令数
现在,我们来计算GPU在执行这个任务时,总共发出了多少条计算指令。
计算公式(公式1):
`总指令数 = (SQ_INSTS_VALU × 4) + SQ_INSTS_SALU`
原理讲解:
- 为什么 `SQ_INSTS_VALU` 要乘以4?这是因为在AMD GPU(MI60/MI100)的架构中,每个计算单元(CU)内部有4个SIMD矢量单元。该指标记录的是每个SIMD单元的指令数,所以需要乘以4来得到整个CU的向量指令总数。
- 标量单元每个CU只有一个,所以 `SQ_INSTS_SALU` 不需要倍增。
步骤三:计算理论峰值与实测性能
这一步我们要算出GPU的"理论极限"和"实际表现"。
- 计算理论峰值GIPS(公式3):
- `CU数量`: 你的GPU的计算单元数量(MI60是64个,MI100是120个)。
- `波前大小`: 对于HPC GPU,通常是64个线程。
- `IPC`: 理论上取1(即每个周期执行1条指令)。
- `频率`: 以GHz为单位的核心频率。
- 计算实测GIPS(公式4):
`峰值GIPS = CU数量 × 波前大小 × IPC × 频率`
`实测GIPS = 总指令数 / (64 × 10^9 × 运行时间)`
原理讲解:这里除以64是因为我们要将总指令数归一化到"波前"这个基本执行单位,以便进行公平的架构间比较。
步骤四:计算指令强度性能
这个指标告诉我们,每从内存搬运一个字节的数据,GPU能执行多少条指令。它决定了你的程序在屋顶线图上的水平位置。
计算公式(公式2):
`指令强度性能 = 总指令数 / [64 × (读取字节数 + 写入字节数) × 运行时间]`
避坑指南:
- 再次注意,`读取字节数` 和 `写入字节数` 需要由 `FETCH_SIZE` 和 `WRITE_SIZE` 从KB转换为Byte。
- 这个公式计算的是"性能",而非绝对的"强度",这是受限于 `rocProf` 工具的能力。但它足以用于在屋顶线图中定位。
步骤五:绘制屋顶线图并分析
现在,让我们把所有的数据整合到一张图上。
- 绘制天花板:
- 在图上画一条水平线,其Y轴值就是你在步骤三计算出的 `理论峰值GIPS`。这是你的"计算天花板"。
- 画一条斜线,其斜率等于你用BabelStream测出的 实际内存带宽(GB/s)。这是你的"内存带宽天花板"。两条线的交点就是GPU的峰值性能点。
- 标记实际性能点:
- 根据步骤四计算出的 `指令强度性能`(作为X坐标)和步骤三计算出的 `实测GIPS`(作为Y坐标),在图上画出一个点。
- 结果分析:
- 如果你的点靠近水平线下方,说明程序是内存瓶颈。优化重点应放在减少内存访问、优化数据局部性上。
- 如果你的点靠近斜线下方,说明程序是计算瓶颈。优化重点应放在提高计算效率、减少指令数上。
- 如果点在中间,说明两者都有优化空间。
成果验证:如何判断你成功了?
完成以上步骤后,你应该得到一张类似下图的指令屋顶线模型:
- 图上清晰标有计算和内存两条天花板。
- 你分析的程序内核,其性能点正确地绘制在图上。
- 你能根据点的位置,清晰地判断出该内核的主要性能瓶颈是内存还是计算。
结尾与下一步
恭喜你!通过这五个步骤,你已经成功地为AMD GPU构建了一个专业的指令屋顶线模型。这个过程从收集数据开始,通过一系列明确的公式进行计算,最终通过可视化图形得出结论,逻辑清晰,一步一个脚印。
记住,所有性能优化的第一步都是精准的测量与分析。指令屋顶线模型就是你手中最强大的"诊断仪"。
动手试试吧!在你的AMD GPU上,找一个你关心的程序,按照这个流程走一遍。欢迎在评论区分享你绘制的屋顶线图,或者在此过程中遇到的任何问题,我们一起探讨解决!
下一步学习建议:
- 尝试分析同一个程序中的不同内核,比较它们的性能特征。
- 深入研究ROCProfiler的其他指标,尝试构建更复杂的性能模型。
- 学习如何根据屋顶线模型的诊断结果,对代码进行具体的优化(例如,使用共享内存来缓解内存瓶颈)。
祝你探索顺利,性能优化之旅愉快!
——威辰新创
本文资料引用自:https://arxiv.org/abs/2110.08221