3. Nsight Compute入门:安装与配置、内核分析视图、性能指标解读、源代码关联
说实话,我见过太多同学在CUDA优化上花了大把时间,结果全靠猜。拍脑袋改代码,跑一下看快没快,没快再改——这哪叫优化?这叫碰运气。
Nsight Compute,就是那个能让你告别「盲人摸象」的工具。它能把GPU内核里每一笔账都算得清清楚楚。今天我就带你把它用起来。
3.1 安装与配置:别在这步卡住
安装其实没什么好说的,去NVIDIA官网下载就行。但我得提醒你几个坑,都是我曾经踩过的。
安装完成后,打开它。你会看到一个启动界面,让你选择分析模式:
- 本地分析:直接在你这台机器上跑。最常用。
- 远程分析:连到另一台机器上跑。我在服务器集群上干活时常用这个。
我个人习惯用命令行启动,因为可以写脚本批量跑。命令很简单:
ncu --set full -o my_kernel_profile ./my_cuda_app
这条命令的意思是:用完整分析模式(--set full),把结果输出到文件(-o),然后运行你的程序。跑完之后,用ncu-ui my_kernel_profile.ncu-rep打开结果文件,就能看到图形界面了。
--set full,那会收集所有数据,慢得很。先用默认模式看看大概,找到瓶颈了再用full模式深挖。
3.2 内核分析视图:一张图看懂一切
打开分析结果后,你会看到几个主要视图。我一个个说。
3.2.1 概要视图(Summary Page)
这是你第一眼看到的东西。它告诉你:
- 哪个内核最耗时
- 占用率怎么样
- 内存带宽用了多少
- 指令吞吐量如何
说白了,这就是一张「体检报告单」。我每次拿到新项目,第一件事就是跑一遍概要视图,看看哪个内核是「胖子」,然后集中火力优化它。
3.2.2 详细视图(Details Page)
点进某个内核,你会看到详细视图。这里分几个标签页:
- GPU Speed of Light:这个图最直观。它用两个轴告诉你——你的内核是被计算限制了,还是被访存限制了。如果访存条快满了,说明你该优化数据访问模式;如果计算条快满了,说明你该优化计算逻辑。
- Occupancy:占用率。很多人一上来就盯着这个看,觉得越高越好。其实不一定。我遇到过占用率90%但性能很差的情况,为什么?因为线程太多,每个线程分到的寄存器太少,导致寄存器溢出到全局内存,反而更慢。
- Memory Workload Analysis:内存工作负载分析。这里会告诉你L1/L2缓存命中率、全局内存访问效率等。嗯,这里要注意,缓存命中率低不一定就是坏事,得结合你的访问模式来看。
- Compute Workload Analysis:计算工作负载分析。这里会列出各种指令的吞吐量,比如浮点运算、整数运算、特殊函数等。
3.2.3 源代码关联视图(Source Page)
这个功能我特别喜欢。它能直接把性能数据映射到你的源代码行上。你想想看,哪一行代码慢,哪一行代码占用了多少带宽,一目了然。
怎么用?很简单:
- 编译时加上
-lineinfo选项(或者-G,但-G会关掉一些优化,建议用-lineinfo) - 在Nsight Compute里打开结果文件
- 切换到Source视图
- 每一行代码旁边都会显示对应的性能指标
我曾经用这个功能发现了一个隐藏很深的bug。有一行代码看起来只是简单的数组赋值,但性能指标显示它占用了大量带宽。仔细一看,原来那个数组的访问模式是非对齐的,导致每次访问都要多读好几个字节。改完之后,性能直接翻倍。
3.3 性能指标解读:别被数字骗了
Nsight Compute会给你一堆数字。但数字多不代表有用。你得知道哪些是关键。
3.3.1 占用率(Occupancy)
占用率 = 实际活跃的线程束数量 / 理论最大线程束数量。
很多人觉得占用率越高越好。其实不是。我见过一个内核,占用率100%,但性能很差。为什么?因为每个线程做的事情太少,大部分时间花在了线程调度上。
占用率的意义在于:它告诉你还有没有隐藏延迟的空间。如果占用率很低,说明你的内核可能被延迟限制了,可以考虑增加线程数或者减少每个线程的资源消耗。
3.3.2 内存带宽(Memory Bandwidth)
这个指标直接告诉你:你的内核把显存带宽用到了什么程度。
如果带宽利用率低于50%,说明你的访存模式有问题。常见原因:
- 非合并访问(non-coalesced access)
- 缓存命中率太低
- 数据复用不够
如果带宽利用率接近100%,说明你的内核是访存受限的。这时候优化计算逻辑没用,得优化数据访问。
3.3.3 指令吞吐量(Instruction Throughput)
这个指标告诉你:你的计算单元忙不忙。
如果指令吞吐量很低,但带宽利用率很高,说明你的内核是访存受限的。反过来,如果指令吞吐量很高,但带宽利用率很低,说明你的内核是计算受限的。
嗯,这里要注意:指令吞吐量高不一定就好。如果大部分指令都是整数运算,而你的算法需要浮点运算,那说明你的实现有问题。
3.4 知识体系:一张图看懂
下面这张图是我自己画的,把Nsight Compute的核心逻辑串起来了。你一看就明白。
3.5 实战建议:从入门到会用
最后,给你几条实战建议:
- 先跑默认模式:别一上来就开full模式,那会收集太多数据,反而让你眼花缭乱。先看看概要视图,找到最耗时的内核。
- 关注瓶颈,而不是完美:你的目标是让内核跑得更快,不是让所有指标都完美。占用率80%还是90%不重要,重要的是你的内核是不是被某个资源卡住了。
- 结合源代码看:光看指标没用,你得知道是哪行代码导致的。源代码关联视图就是干这个的。
- 多做对比:改代码之前跑一次,改之后跑一次,对比两个结果。我习惯把每次优化的结果都保存下来,方便回溯。
好了,Nsight Compute的入门就讲到这里。工具给你了,剩下的就是多练。你跑得越多,对性能指标的直觉就越准。到那时候,你一眼就能看出内核的问题在哪。
想要更多资料,联系可可