3、NVIDIA Nsight Systems入门:安装与配置、基本界面介绍、首次性能追踪
说实话,Nsight Systems 是我日常工作中用得最多的工具之一。它不像 Nsight Compute 那样盯着单个 kernel 看,而是从全局视角帮你梳理整个应用的性能瓶颈。说白了,它就是 GPU 性能分析的「全景相机」。
我记得第一次用这个工具时,差点被它的界面吓到——怎么这么多面板?但用顺手之后,你会发现它其实非常直观。今天我们就从零开始,把它装好、配好,然后跑一次完整的性能追踪。
3.1 安装与配置
安装这块其实没什么坑,但有几个细节我踩过,得跟你提个醒。
3.1.1 系统要求
先看看你的环境是否满足条件:
| 组件 | 最低要求 | 推荐配置 |
|---|---|---|
| 操作系统 | Windows 10 / Ubuntu 18.04 | Windows 11 / Ubuntu 22.04 |
| GPU | NVIDIA Kepler 架构及以上 | Turing 或 Ampere 架构 |
| CUDA 版本 | CUDA 10.0+ | CUDA 11.8+ |
| 磁盘空间 | 2 GB | 10 GB(用于保存 trace 文件) |
sudo apt install libxcb-xinerama0。
3.1.2 下载与安装
去 NVIDIA 开发者官网下载 Nsight Systems。我个人习惯用命令行安装,干净利落。
# Ubuntu / Debian 系
sudo dpkg -i NsightSystems-linux-public-2023.3.1.97-3304643.deb
# 或者用 runfile 安装
chmod +x NsightSystems-linux-public-2023.3.1.97-3304643.run
sudo ./NsightSystems-linux-public-2023.3.1.97-3304643.run
Windows 用户直接双击 exe 安装包就行,一路 Next。嗯,这里要注意:安装路径不要有中文,否则可能报奇怪的错误。
3.1.3 环境变量配置
装完之后,建议把 nsys 命令行工具加到 PATH 里。我一般这样配:
# 编辑 ~/.bashrc 或 ~/.zshrc
export PATH=/opt/nvidia/nsight-systems/2023.3.1/bin:$PATH
# 验证是否安装成功
nsys --version
如果看到版本号输出,说明装好了。如果提示「command not found」,检查一下安装路径对不对。
alias nsys='/opt/nvidia/nsight-systems/2023.3.1/bin/nsys',省得每次敲长路径。
3.2 基本界面介绍
打开 Nsight Systems,你会看到这样一个界面。别慌,我们一个一个面板来看。
3.2.1 主窗口布局
整个界面分成四个主要区域:
- 菜单栏和工具栏:最上面一排,文件、编辑、视图这些。常用的就是「File > Open」和「File > New Project」。
- 项目浏览器:左侧面板,显示你打开过的 trace 文件和项目结构。
- 时间轴视图:中间最大的区域,这是核心。所有 GPU 活动、CPU 调用、内存操作都在这里以时间线的形式展示。
- 详细信息面板:右侧或底部,当你点击时间轴上的某个事件时,这里会显示它的详细参数。
你想想看,这就像看一部电影的剪辑软件——时间轴是主战场,其他面板都是辅助信息。
3.2.2 时间轴视图详解
时间轴视图里,每一行代表一个「轨道」。常见的轨道有:
- CUDA HW:显示 GPU 硬件上的活动,比如 kernel 执行、内存拷贝。
- CUDA API:显示 CPU 端调用的 CUDA API 函数,比如 cudaMemcpy、cudaLaunchKernel。
- NVTX:如果你在代码里加了 NVTX 标记,这里会显示自定义的事件范围。
- Threads:显示 CPU 线程的活动,比如函数调用栈。
我记得第一次看这个时间轴时,发现 kernel 执行和内存拷贝之间有明显的空隙。当时我以为是 GPU 在偷懒,后来才发现是 CPU 端提交命令太慢,导致 GPU 饿着了。这就是 Nsight Systems 的价值——让你看到「看不见的等待」。
3.2.3 常用操作
几个我每天都会用的操作:
- 缩放:滚轮缩放时间轴,或者按住 Ctrl 拖动鼠标框选区域。
- 测量:按住 Shift 然后拖动,可以测量两个事件之间的时间差。
- 搜索:按 Ctrl+F 搜索 kernel 名称或 API 函数。
- 导出:File > Export 可以导出为 CSV 或 JSON 格式,方便做进一步分析。
3.3 首次性能追踪
理论说完了,我们来实战。我会用一个简单的 CUDA 程序做演示。
3.3.1 准备测试程序
先写一个简单的向量加法程序,保存为 vector_add.cu:
#include <cuda_runtime.h>
#include <stdio.h>
__global__ void vec_add(float *a, float *b, float *c, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
c[idx] = a[idx] + b[idx];
}
}
int main() {
int n = 1 << 20; // 1M 个元素
size_t bytes = n * sizeof(float);
float *h_a, *h_b, *h_c;
float *d_a, *d_b, *d_c;
// 分配主机内存
h_a = (float*)malloc(bytes);
h_b = (float*)malloc(bytes);
h_c = (float*)malloc(bytes);
// 初始化数据
for (int i = 0; i < n; i++) {
h_a[i] = 1.0f;
h_b[i] = 2.0f;
}
// 分配设备内存
cudaMalloc(&d_a, bytes);
cudaMalloc(&d_b, bytes);
cudaMalloc(&d_c, bytes);
// 拷贝数据到 GPU
cudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice);
// 启动 kernel
int threads = 256;
int blocks = (n + threads - 1) / threads;
vec_add<<<blocks, threads>>>(d_a, d_b, d_c, n);
// 拷贝结果回 CPU
cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost);
// 验证结果
printf("c[0] = %f\n", h_c[0]);
// 清理
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
free(h_a);
free(h_b);
free(h_c);
return 0;
}
编译它:
nvcc -o vector_add vector_add.cu
3.3.2 运行性能追踪
现在用 nsys 来追踪这个程序。最基本的命令是:
nsys profile -o vector_add_report ./vector_add
解释一下参数:
profile:告诉 nsys 我们要做性能追踪。-o vector_add_report:指定输出文件名为 vector_add_report,默认会生成 .nsys-rep 文件。./vector_add:要追踪的可执行文件。
运行后,你会看到类似这样的输出:
Collecting data...
Processing events...
Generated: /home/user/vector_add_report.nsys-rep
嗯,这里要注意:如果程序运行时间很短(比如几毫秒),nsys 可能采集不到足够的数据。我建议在测试程序里加一些循环,让 GPU 多跑几次。
3.3.3 打开并分析报告
用 Nsight Systems GUI 打开生成的 .nsys-rep 文件:
nsys-ui vector_add_report.nsys-rep
或者直接在 GUI 里 File > Open。
打开后,你会看到时间轴视图。放大到 kernel 执行的部分,你应该能看到:
- 两个 cudaMemcpy 操作(Host to Device)
- 一个 vec_add kernel 执行
- 一个 cudaMemcpy 操作(Device to Host)
这就是一个典型的「三段式」GPU 工作流:数据上传 → 计算 → 结果下载。
3.3.4 常用追踪选项
nsys 有很多选项,我常用的几个:
| 选项 | 作用 | 示例 |
|---|---|---|
--trace=cuda,osrt |
只追踪 CUDA 和操作系统运行时调用 | nsys profile --trace=cuda,osrt ./app |
--stats=true |
在终端输出统计摘要 | nsys profile --stats=true ./app |
-c cudaProfilerApi |
通过 cudaProfilerStart/Stop 控制追踪范围 | nsys profile -c cudaProfilerApi ./app |
--duration=10 |
只追踪前 10 秒 | nsys profile --duration=10 ./app |
--trace 限制,结果 nsys 采集了所有系统调用,生成的文件有 20 多 GB。打开时直接卡死。建议第一次跑时先用 --trace=cuda 缩小范围。
3.4 本章小结
今天我们走完了 Nsight Systems 的入门流程:安装、界面认识、第一次性能追踪。你想想看,其实核心就三件事:装好工具、看懂时间轴、跑一次 trace。
我个人觉得,Nsight Systems 最厉害的地方不是它有多少功能,而是它让你「看到」程序的执行过程。很多性能问题,光看代码是看不出来的,必须跑一次 trace 才能发现。
下一章我们会深入时间轴视图,学习如何解读那些花花绿绿的条条块块。到时候我会分享一些我实际项目中遇到的「诡异」性能问题,保证让你大开眼界。