第一章:报告初印象与 Summary 细读 ⭐教你读懂 Nsight Compute 报告 系列合集⭐
第一章:报告初印象与 Summary 细读
序章里报告已经采好打开了,本章就从上到下、从左到右,把这个界面过一遍。界面里的信息很多,有轻有重,重要的就细讲,了解的就带过,具体的针对性的讲解之后单独成章。
界面初印象

最顶上一排是 Main Menu:File、Connection、Debug、Profile、Tools、Window、Help。
- File 管理报告文件和工程,打开、关闭、另存为这些入口都在这里。不过作者的报告是直接用命令行打开的,工程已经自动建好、报告也已经打开了,所以用不到;
- Connection 管理和目标机器的连接,ncu 支持本地或者 SSH 连上正在运行的程序边跑边采,但作者走的是先完整采集、再单独打开报告文件的路线,所以用不上;
- Debug 管理现场调试,能把程序暂停、单步执行,盯每一次调用,对这份已经采完的报告同样用不上;
- Profile 管理具体的采集配置,比如调整采集细致程度,配置对某个 kernel 进行特殊采集、管理对比基准。作者的报告还用不到这些比较高级的功能;
- Tools 是各类工具窗口和软件设置的入口,默认配置就好;
- Window 管理界面里各个 Tool Windows 的布局。Tool Windows 就是 Main Menu 下方工作区里那些可以拖动、调整停靠位置的面板。Window 里面有保存和恢复窗口布局的功能,各个面板调整到符合个人习惯后把布局保存一下,之后万一拖乱了能一键恢复;
- Help 查看软件版本信息、打开官方文档。
Main Menu 下面那排按钮是 Main Toolbar。它其实就是把 Main Menu 里一系列高频动作又做成一个快捷按钮,基本都属于实时采集和现场调试的入口,这一排现在一个都用不上。
再往下,左边 Project Explorer 是项目管理器,打开报告的时候工程已经自动建好了,不必过多关注;右边 Documents,就是之后真正主要关注的部分。
Documents 页面
报告头
报告打开后,Documents 最顶部已经显示打开了 reduce-ill.ncu-rep,再下方是 kernel 的基本运行信息:

报告只针对一个 kernel 且只采集了一次,所以这份报告自始至终只有一条结果,会使很多筛选和对比性质的功能都无效,但这样也能更好地突出重点。从左往右看:
| 项 | 值 | 含义 |
|---|---|---|
| 勾选框(方块) | 已勾选(方块涂为实心蓝色) | 在多结果的场景中,选中某个结果做表头汇总、结果导出、对比基准这类操作。对于本报告就无作用了 |
| Current Result | 552 - reduce_ill | 一个报告里可以有多条采集结果,这个下拉框用来切换当前看哪条。对于本报告,没什么可切的。 ncu 拿"调用编号 + kernel 名"命名。这里 552 是 API Call ID,是指这条 kernel 是采集期间 CPU 发起的第 552 次 CUDA API 调用 |
| 筛选按钮(小沙漏) | 空 | 按条件过滤结果列表,高级功能。对于本报告,没什么好筛选的,也无作用了 |
| Size | (8192, 1, 1)x(256, 1, 1) | kernel 的 grid 的三维大小和 block 的三维大小 |
| Time | 318.43 us | kernel 的执行时间,以 us 为单位 |
| Cycles | 443,927 | kernel 的执行时间,以 GPU 周期为单位 |
| GPU | 0 – NVIDIA GeForce RTX 3090 | kernel 的运行所在显卡 |
| SM Frequency | 1.39 GHz | 显卡上各 SM 的实际平均频率 SM Frequency = Cycles / Time |
| Process | [389058] reduce | 采集时目标进程的 PID 和名字 |
| Attributes | 齿轮图标 | 点一下会跳到 Details 页的 Launch Statistics,是更详细的启动 kernel 时的配置信息,先只了解一下 |
报告主体
再往下的一排标签就是报告的七个页面:Summary、Details、Source、Context、Comments、Raw、Session,整个合集的主线就围绕它们推进:
- Summary 是采集结果的一览表,双击某一条数据就会跳到对应的 Details,界面最下方是 ncu 官方给出的优化建议,按预计的加速空间从高到低排;
- Details 是所有指标数据的大合集,采到的东西全在这页,被切成一个个 section,ncu 内置一套分析规则,得出的警告也挂在各自 section 头上,这是信息量巨大的一页,是之后的重点;
- Source 把 GPU 的汇编码 SASS 和 CUDA-C 源码对照起来,把指标挂到每条指令、每行源码上,指出硬件计数器翻译回代码对应哪一行,也是之后的重点;
- Context 记录采集期间的 CPU 调用栈和 NVTX 状态;
- Comments 用来给报告和各 section 写备注;
- Raw 是全部指标的原始账本,记录所有采集到信息的原始值和单位,带 filter 框能按名字筛;
- Session 记录这次采集的环境情况,包括命令行怎么启动的采集、采集主机和目标设备的属性信息。
标签栏右边还有 Compare、Tools、View、Export 和一个三条横线的小按钮,分别管对比基准、附属工具、视图切换和导出。最后那个小按钮是关于规则应用的选项。这几个按钮里最常用的就是 Export,其它的先不展开。
Summary 页面
数据列表
再往下就是本页的主角,Summary 页面,左上角的两个箭头围成圈的按钮是转置数据表格。

各指标具体如下:
| 项 | 值 | 含义 |
|---|---|---|
| ID | 0 | 这条结果在报告里的编号 |
| Estimated Speedup [%] | 86.10 | ncu 的规则引擎估计的优化空间上限,意思是"按它的建议改,理论上最多能快这么多" |
| Function Name | reduce_ill | kernel 名字 |
| Demangled Name | reduce_ill(float *, float *, int) | kernel 名反修饰还原出的 C++ 完整签名函数名 |
| Duration [us] | 318.43 | kernel 的执行时间 |
| Runtime Improvement [us] | 274.16 | 按 ncu 建议改完后理论上能省下的执行时间,是 ncu 拿 Duration 乘上 Estimated Speedup 算出来的 |
| Compute Throughput [%] | 15.98 | 计算侧利用率 |
| Memory Throughput [%] | 80.44 | 内存侧利用率 |
| # Registers | 36 | 每个线程用了 36 个寄存器 |
| Grid Size | 8192, 1, 1 | grid 三维大小 |
| Block Size | 256, 1, 1 | block 三维大小 |
我们重点关注:
- Duration,执行时间,硬件计时器测的,只算 kernel 真正在 GPU 上跑的那段时间,启动和数据搬运这些开销都不掺在里面,我们做完算子优化后,比较它就可以知道是不是快了,快了多少。
- Compute Throughput,计算侧利用率,算法是把 SM 里各条计算管线,整数、浮点、访存指令这些各自的实际吞吐除以各自的理论峰值,再取其中的最高者。这个值越高,代表计算单元越逼近自己的算力极限,本报告只有 15.98%,说明算力大量闲置,优化的空间不在这里。
- Memory Throughput,内存侧利用率,算法是从 L1TEX 到 L2 再到显存这条链路上各通路的实际吞吐除以各自的理论峰值,再取其中的最高者。这个值越高,代表访存侧越逼近自己的带宽极限,80.44% 属于较高的范畴了,说明数据搬运非常繁忙,再配合 Compute Throughput 的低值,我们就可以读出这个 kernel 的问题出在内存侧,计算单元大部分时间都在干等数据搬运到位,所以优化空间就是怎么优化数据的搬运链路,尽量减少计算单元可以计算但数据没送到而不得不干等的时间。
ncu 优化建议
表格下面还有一块区域,列着 ncu 给出的优化建议,叫 Prioritized Rules,按预计加速比从高到低排序。每条建议最左边是规则名,指出当前的数据触发了 ncu 建议库中的哪一条,其下方是 ncu 的判断预计加速比,意为如果按这条建议把问题优化好了,理论上预计能提升这么多。右侧具体描述问题是什么,最右侧有个小圆圈箭头,点开会展开和这条建议强相关的指标数据。作者这份报告 ncu 给出了三条建议:

- Uncoalesced Global Accesses,未合并的全局访问,预计加速 86.10%,说这个 kernel 存在未合并的全局访存,一共多产生了 14,680,064 个 sector,占全部 16,785,408 个 sector 的 87%;更多信息可以去 L2 Theoretical Sectors Global Excessive 表找这些多余 sector 主要出在哪些代码位置。这个反映的正是序章中的病态一,当时算过病态一把从显存取数的读流量放大了 8 倍,8 份流量里 7 份白搬,如果内存是合并访问,硬件就不用额外多搬近 1468 万个 sector,7/8 = 87.5%,正对应了此处 ncu 指出来的 87%。点开圆圈箭头,展开的正是官方说明里指的那张 L2 Theoretical Sectors Global Excessive 表,它记录了实际采到的 sector 数减去理想情况下装下同样有效字节所需的最少 sector 数,即白搬的次数,给出的建议也很明确,减少 L2 缓存中多余的 Wavefronts 数量,和优化为内存合并访问一个意思。
- L1TEX Global Load Access Pattern,L1TEX 全局加载访问模式不佳,预计加速 80.90%,说 L1TEX 的全局加载访存模式可能不是最优的,平均每个 sector 传输的 32 字节里,每个线程只利用了 4.0 字节,这可能是由线程间的地址间隔造成的;更多信息可以去 Source Counters 部分查未合并的全局加载。这个和第一条是同一个问题,只是视角不同,第一条从 L2 的 sector 流量算总账,这条从 L1TEX 的字节利用率找原因。序章中也算过,一个 warp 每个 thread 只用 4 字节、硬件却必须搬 32 字节,"每个线程只用 4 字节"正是该建议的直接写照。点开圆圈箭头,展开的表格就两行:第一行是 Bytes per Sector 4.0,指出的就是这个现状,给出的建议是把每个 sector 平均用到的字节数往 32 字节上提;第二行是 L1TEX 的吞吐 92.45%,想说的是 L1TEX 越忙,这个问题就越严重。所以本条建议本质上和上一条是一个意思。
- L1TEX Global Store Access Pattern,L1TEX 全局存储访问模式不佳,预计加速 80.90%,说的和上一条几乎一字不差,只是把加载换成了存储,展开的表格都完全一样,其本质上也和上一条一个意思。
这一章到这里就结束了,现在我们已经能看懂报告的首页,并且能粗略地定位问题在哪里了,但要具体的找出问题具体藏在链路的哪一级、代码的哪一行,还得去 Details 页里翻。下一章我们就来重点关注 Details 页面的核心数据。

浙公网安备 33010602011771号