4、性能分析工具入门:NVIDIA Nsight Systems、Nsight Compute、nvidia-smi的基本使用

好,咱们进入实战环节。前面聊了那么多带宽的理论,现在该看看怎么用工具抓住它了。

说实话,我见过不少工程师,代码写得飞起,一跑起来性能拉胯。问他为什么慢,答不上来。为什么?因为没用量化工具。凭感觉优化,那是玄学。今天我就带你认识三把最趁手的「手术刀」。

4.1 第一把刀:nvidia-smi —— 系统级监控

这是最基础的,也是我每天必敲的命令。它就像汽车的仪表盘,告诉你发动机转速、油温、水温。

基本用法

nvidia-smi

敲下去,你会看到当前GPU的型号、显存使用、温度、功耗、风扇转速。嗯,这里要注意:显存占用 ≠ 显存带宽利用率。很多人看到显存用了80%就慌了,其实不一定有问题。

我常用的几个参数

  • nvidia-smi -l 1:每秒刷新一次,持续监控。我习惯开着它跑程序,看显存和功耗曲线。
  • nvidia-smi dmon -s pucvmet:更详细的监控模式,能看到PCIe带宽、电源状态。
  • nvidia-smi --query-gpu=memory.used,utilization.memory --format=csv:输出CSV格式,方便脚本处理。
我的小技巧: 如果你发现显存占用很高,但GPU利用率(Utilization)很低,大概率是带宽瓶颈。因为GPU在等数据,没活干。

4.2 第二把刀:Nsight Systems —— 时间线分析

这个工具,说白了就是给程序拍X光片。它能告诉你CPU和GPU各自在干什么,哪个阶段在等数据。

什么时候用它?

当你发现程序跑得慢,但不知道慢在哪一段。比如:是数据加载慢?还是计算慢?还是同步开销大?

基本用法

nsys profile -o my_profile ./my_app

运行完后会生成一个 .nsys-rep 文件。用Nsight Systems GUI打开,你会看到一条时间轴。

我重点关注什么?

  • GPU Kernels:看每个kernel的执行时间。如果某个kernel特别长,点进去看。
  • MemCpy (H2D/D2H):主机到设备、设备到主机的数据拷贝。如果这里占了大量时间,说明数据传输是瓶颈。
  • CPU Activity:看CPU在忙什么。有时候CPU在等GPU,有时候GPU在等CPU。

避坑指南: 我曾经遇到一个项目,GPU利用率只有30%。用Nsight Systems一看,发现每次kernel启动前,CPU都在做一次同步等待。去掉那个多余的 cudaDeviceSynchronize(),利用率直接飙到85%。

4.3 第三把刀:Nsight Compute —— 内核级剖析

这是最精细的工具。如果说Nsight Systems是看全局,那Nsight Compute就是看每个kernel的内部细节。它能告诉你:你的kernel到底是不是带宽瓶颈。

基本用法

ncu -o my_kernel_profile ./my_app

同样生成一个 .ncu-rep 文件。打开后,你会看到密密麻麻的指标。

我只看这几个关键指标:

指标 含义 我的判断标准
Memory Throughput 实际达到的显存带宽 如果远低于理论带宽(比如A100是2TB/s,你只跑到200GB/s),说明有瓶颈
L1/L2 Hit Rate 缓存命中率 命中率低,说明数据局部性差,带宽浪费在重复加载上
Occupancy SM上活跃的warp数量 如果Occupancy低,可能是寄存器或共享内存用太多
Compute Utilization 计算单元利用率 如果Memory Throughput高但Compute Utilization低,就是典型的带宽瓶颈

怎么判断是不是带宽瓶颈?

你想想看,如果Memory Throughput接近理论带宽,但Compute Utilization很低,那你的kernel就是在「等数据」。说白了,计算单元在摸鱼,因为数据喂不过来。

注意: 不要只看一个指标。比如Occupancy高不一定好,如果每个线程都在访问全局内存,高Occupancy反而加剧带宽竞争。我见过有人把Occupancy调到100%,结果带宽反而下降了。

4.4 三把刀怎么配合使用?

我个人的工作流是这样的:

  1. 先用nvidia-smi:看看整体资源使用情况,有没有异常。
  2. 再用Nsight Systems:找到最耗时的阶段,是数据拷贝还是kernel执行。
  3. 最后用Nsight Compute:针对最耗时的kernel,深入分析是不是带宽瓶颈。

举个例子。有一次我优化一个图像处理程序。先用nvidia-smi发现显存占用高但利用率低。然后用Nsight Systems看到,大部分时间花在了一个叫 filter_kernel 的kernel上。最后用Nsight Compute分析这个kernel,发现Memory Throughput只有理论带宽的30%,L1命中率不到10%。

嗯,问题找到了。数据访问模式太随机,缓存根本帮不上忙。后面我们就会讲怎么通过合并访问、共享内存来优化它。

我的建议: 刚开始用这些工具时,不要被海量指标吓到。先抓住我说的那几个关键指标。用熟了再慢慢深入。记住,工具是帮你定位问题的,不是让你炫技的。

好了,这一章就到这。下一章我们开始讲怎么用这些工具定位具体的带宽瓶颈,我会拿一个真实的代码案例来演示。