3、Profiling工具入门:NVIDIA Nsight Systems安装与使用、Nsight Compute基本操作、命令行profiling(nvprof/ncu)、关键性能计数器解读、生成性能分析报告。

说实话,很多同学写CUDA代码,跑通了就觉得万事大吉。但性能怎么样?瓶颈在哪?完全没概念。我刚开始做GPU优化那会儿,也犯过这毛病。直到有一次,一个看起来挺简单的kernel,怎么调都跑不满,折腾了两天。后来一用profiling工具,才发现是全局内存访问模式出了问题。嗯,从那以后,我写代码必做profiling。

这一章,咱们就聊聊NVIDIA的几款核心profiling工具。说白了,它们就是你的“GPU听诊器”。

3.1 NVIDIA Nsight Systems:宏观视角的“时间轴”

Nsight Systems,我习惯叫它“Nsys”。它主要看的是整个应用的时间线。CPU在干嘛?GPU在干嘛?数据传输花了多久?kernel执行和内存拷贝有没有重叠?这些宏观问题,用它看最清楚。

3.1.1 安装与配置

安装其实很简单。去NVIDIA官网下载,或者用包管理器。我个人习惯用命令行安装,干净利落。

# Ubuntu/Debian
sudo apt-get install nsight-systems

# 或者下载 .run 文件
chmod +x NsightSystems-linux-public.run
sudo ./NsightSystems-linux-public.run

装好后,终端敲 nsys 就能看到帮助信息。Windows用户直接双击桌面图标就行。

小提示: 我建议你配个环境变量,把nsys加到PATH里。省得每次都要敲全路径。

3.1.2 基本使用:抓取一次Profile

抓取profile,最常用的就是 nsys profile 命令。后面跟上你的可执行文件。

nsys profile -o my_profile ./my_cuda_app

这条命令会运行 my_cuda_app,并把结果保存到 my_profile.qdrep 文件里。 -o 指定输出文件名。

你想想看,如果我只想抓kernel执行,不想看API调用,怎么办?加个 -t cuda 参数就行。

nsys profile -t cuda -o kernel_only ./my_cuda_app

这招我在排查“kernel启动开销过大”时经常用。只关注CUDA相关事件,数据量小,分析起来也快。

3.1.3 图形界面:可视化时间线

抓完profile,用 nsys-ui 打开 .qdrep 文件。你会看到一个类似Gantt图的时间轴。

上边是CPU活动,下边是GPU流。不同颜色代表不同事件:

  • 紫色:内存拷贝(Memcpy)
  • 绿色:Kernel执行
  • 黄色:CUDA API调用

一眼就能看出,你的程序是“计算密集”还是“访存密集”。我曾经优化过一个模型,一看时间线,好家伙,80%的时间都在做Host到Device的数据拷贝。那还优化啥kernel?先搞异步传输啊!

3.2 Nsight Compute:微观视角的“手术刀”

Nsight Compute,简称“Ncu”。如果说Nsys是看全局的,那Ncu就是盯着单个kernel,看它的内部细节。指令吞吐、内存带宽、占用率……这些关键指标,全靠它。

3.2.1 基本操作:Profile单个Kernel

用ncu profile一个kernel,命令也很直接:

ncu -o my_kernel_profile ./my_cuda_app

它会运行你的程序,并生成 .ncu-rep 文件。默认情况下,ncu会profile所有kernel。如果只想看某一个,可以用 --kernel-name 过滤。

ncu --kernel-name "myKernel" -o single_kernel ./my_cuda_app

这个功能特别实用。项目大了,kernel几十个,一个个看太费劲。先定位到最耗时的那个,再用ncu深挖。

3.2.2 关键性能计数器解读

打开 .ncu-rep 文件,你会看到一堆指标。别慌,咱们抓重点。

指标名称 含义 理想值
Occupancy 每个SM上活跃的warp数量与最大warp数量的比值 越高越好,但并非绝对
Memory Throughput 全局内存的读写吞吐量 接近理论峰值
Compute Throughput 计算单元的利用率 接近理论峰值
L1/L2 Hit Rate 缓存命中率 越高越好
Warp Stall Reasons warp停顿的原因(如等待数据、等待计算) 无停顿最佳

举个例子。有一次我优化一个矩阵乘法,Occupancy很高,但Memory Throughput很低。我一看Warp Stall Reasons,发现大部分warp都在“等待数据”。这说明什么?说明内存访问模式有问题,导致缓存命中率低。后来改成共享内存,吞吐量直接翻倍。

核心思路: 不要只看Occupancy。它只是“能跑多少线程”,不代表“跑得多快”。真正的瓶颈,往往在Memory Throughput和Compute Throughput上。

3.3 命令行Profiling:nvprof与ncu

老玩家可能还记得 nvprof。它是CUDA 10之前的官方profiling工具。现在虽然被ncu取代了,但很多老项目还在用。我建议你至少知道它怎么用,万一遇到老代码呢?

3.3.1 nvprof(经典但已弃用)

nvprof --print-gpu-trace ./my_cuda_app

这条命令会打印出每个kernel的耗时、占用率、内存传输量等。简单粗暴,适合快速看一眼。

注意: nvprof在CUDA 11之后就不再更新了。新项目请用ncu。我见过有人还在用nvprof,结果新显卡的某些特性根本抓不到。

3.3.2 ncu(现代推荐)

ncu的命令行模式更强大。除了生成报告,还能直接输出文本结果。

ncu --set full --page details ./my_cuda_app

--set full 会收集所有指标,--page details 会显示详细分析。适合在无图形界面的服务器上使用。

我个人习惯在开发机上用图形界面,在集群上用命令行。两者结合,效率最高。

3.4 生成性能分析报告

分析完数据,怎么给别人看?或者怎么存档?NVIDIA提供了报告导出功能。

3.4.1 从Nsight Systems导出

在Nsys的图形界面里,点 File -> Export。可以导出为 .csv 或 .txt 格式。我一般导出CSV,方便用Python做二次分析。

3.4.2 从Nsight Compute导出

在Ncu的图形界面里,点 File -> Export Report。可以导出为 .csv、.json 或 .html 格式。HTML格式最直观,可以直接发给同事看。

我曾经给团队做过一次性能优化分享,就是把ncu的报告导出成HTML,然后贴在Wiki上。大家一看就懂,省了不少口舌。

3.5 本章知识体系

下面这张图,帮你理清本章的核心逻辑。

CUDA Profiling 工具 Nsight Systems 宏观时间线分析 CPU/GPU活动重叠 数据传输与Kernel执行 Nsight Compute 微观Kernel分析 指令吞吐与内存带宽 Occupancy与Stall分析 命令行工具 nvprof (经典) ncu (现代) 性能分析报告

这张图展示了本章的核心脉络。从宏观的Nsight Systems,到微观的Nsight Compute,再到灵活的命令行工具,最终都指向一个目标:生成可读的性能分析报告,指导我们做优化。

好了,工具就介绍到这儿。下一章,咱们会拿一个实际的kernel,一步步演示怎么用这些工具找到性能瓶颈。到时候,你会看到这些计数器到底怎么用。

我的建议: 别光看,动手装一个Nsight Systems,跑个你之前的CUDA程序看看。哪怕只是看个时间线,你都会有新发现。

想要更多资料,联系可可