1. 课程导入与性能分析全景
GPU 性能分析的核心目标,不是“让程序跑得更快”这一句口号,而是回答三个可验证的问题:时间花在哪里、硬件为什么没被喂饱、改动之后是否真的变快。在 NVIDIA 平台上,这三个问题分别对应时间线(Timeline)、硬件利用率(Utilization)与指标对比(Metric Comparison)。如果缺少其中任何一环,优化就容易退化为“凭感觉改代码”:把 kernel 改小、把 batch 调大、把精度降一档,却无法说明收益来自哪里、代价落在何处。
Nsight 工具家族正是围绕这条证据链组织的。理解它们的分工,比记住每个按钮更重要。下面这张图给出从“程序整体”到“单个 SM 指令”的观测层级,以及各工具在其中的位置。
为什么必须先看时间线
很多初学者一上手就用 Nsight Compute 抓 kernel 指标,结果看到“显存带宽利用率 85%”就断定是访存瓶颈。但如果时间线显示 GPU 有 40% 的时间处于空闲,真正的问题可能是 CPU 侧数据准备太慢、拷贝与计算没有重叠,或者 kernel 启动次数过多导致调度开销占比过高。此时去优化 kernel 内部的访存模式,收益会被空闲时间稀释。
因此推荐的分析顺序是:先用 Nsight Systems 看全局,确认 GPU 是否被充分利用;再对占用时间最长的 kernel 用 Nsight Compute 下钻。一个典型的判断依据是:若时间线中 GPU 活跃区间占比低于 70%,优先排查 CPU 瓶颈、同步点、拷贝串行化;若 GPU 几乎全程忙碌但吞吐仍不达标,才进入 kernel 内部找瓶颈。
瓶颈定位的基本思路
GPU kernel 的瓶颈通常落在四类资源上:计算单元(SM/FP32/Tensor Core)、显存带宽、延迟隐藏能力(Occupancy 与 Warp 调度)、以及指令开销(分支发散、原子操作、同步)。Nsight Compute 的 Speed of Light 面板用两个百分比快速区分前两类:Compute Throughput 与 Memory Throughput。若前者接近 90% 而后者较低,说明算力吃紧;若后者接近 90%,说明访存受限;若两者都不高,则问题多半在延迟隐藏或指令效率。
举个教学示例(以下数值为合理假设,用于说明判断逻辑,非实测结果):某矩阵乘法 kernel 在 A100 上测得 Compute Throughput 42%、Memory Throughput 88%、L2 命中率 35%。两个吞吐都不低但计算明显偏低,且访存接近饱和,可初步判断为显存带宽瓶颈。进一步查看 Memory Workload Analysis,若发现全局加载事务数远大于理论值,说明访问未合并;此时把线程块内线程按行连续映射、确保相邻线程访问相邻地址,通常能显著降低事务数。修改后复测,若 Memory Throughput 降到 60% 而 Compute Throughput 升到 75%,则说明瓶颈已从访存转移到计算,优化方向随之改变。
本课程要建立的实战能力
本课程不追求把 Nsight 的每个面板讲一遍,而是围绕一条可复现的分析闭环展开:给定一个可运行的 CUDA 程序,能够独立完成“采集时间线 → 识别热点 kernel → 读取关键指标 → 提出假设 → 修改代码 → 复测对比 → 给出结论”的全过程。为此,后续章节会反复使用同一套参照约定:时间以毫秒为单位,吞吐百分比以 Nsight Compute 的 Speed of Light 为准,对比时固定输入规模、GPU 型号与时钟设置,避免把频率波动误判为优化收益。
需要提前建立的一个习惯是:每次只改一个变量,并保留修改前的基线数据。GPU 性能受频率、温度、驱动、编译器版本影响,若一次改动多个因素,即使变快也无法归因。把基线耗时、关键指标、修改内容记录成简表,是后续所有章节都要求的基本功。
| 分析阶段 | 主要工具 | 核心问题 | 典型输出 |
|---|---|---|---|
| 全局时间线 | Nsight Systems | GPU 是否被充分利用 | CPU/GPU 时间线、API 耗时 |
| Kernel 瓶颈 | Nsight Compute | 算力还是访存受限 | Compute/Memory Throughput |
| 指令与源码 | Nsight Compute | 哪一行导致停顿 | Source/SASS 热点、停顿原因 |
| 回归验证 | 两者结合 | 改动是否真实有效 | 基线对比表、指标变化 |