4. Trace采集
Trace采集,说白了就是给GPU程序做「录像」。不是拍照片那种快照,而是连续记录每一帧、每一个kernel、每一次内存拷贝的完整时间线。
我刚开始用Nsight的时候,总觉得Profile就够了。直到有一次,一个模型训练时快时慢,Profile根本看不出问题。Trace一开,真相大白——原来是CPU在等GPU,GPU又在等数据搬运,整个流水线断断续续。嗯,从那以后,Trace就成了我的标配。
4.1 Trace到底是什么?
简单说,Trace就是时间轴上的事件序列。它记录了三类核心信息:
- 时间戳:每个操作开始和结束的精确时刻
- 事件类型:kernel启动、内存拷贝、同步操作、API调用等
- 上下文信息:哪个stream、哪个device、哪个进程干的
你想想看,有了这些数据,你就能回答三个灵魂拷问:
- GPU到底在忙还是在等?
- 瓶颈在计算、访存还是通信?
- 并行度够不够?有没有串行依赖?
核心区别:Profile给你的是「平均值」,Trace给你的是「时间线」。前者告诉你「慢」,后者告诉你「为什么慢」。
4.2 采集配置:别急着点那个按钮
我见过太多人一上来就点「Start Collection」,结果要么数据太大打不开,要么漏掉了关键信息。配置这一步,值得花5分钟认真对待。
4.2.1 采集模式选择
| 模式 | 适用场景 | 开销 |
|---|---|---|
| Full Trace | 首次分析、定位瓶颈 | 高(可能拖慢10-30%) |
| Lightweight Trace | 已知问题、快速验证 | 低(<5%) |
| Range Trace | 只关注某段代码 | 可控 |
我个人习惯:第一次跑Full Trace,摸清整体情况。后面优化迭代时,用Lightweight或者Range模式,只盯关键区域。
4.2.2 关键参数详解
这里有几个参数,我建议你重点关注:
- Buffer Size:Trace数据缓冲区大小。默认值往往不够,尤其是跑大模型时。我曾经因为没调这个,跑了半小时的采集,最后数据全丢了——缓冲区溢出了。建议设到256MB以上。
- Max Duration:最大采集时长。别设太大,5-10秒通常足够发现问题。太长的话,文件会大到打不开。
- Kernel Sampling:是否采样kernel内部细节。开了能看到warp occupancy、memory transactions,但开销翻倍。
- API Tracing:是否记录CUDA API调用。排查驱动层问题时必开。
注意:开启所有选项不等于更好。Trace本身有开销,开得越多,程序行为越可能被改变。这叫「海森堡效应」——你观察它,它就变了。
4.3 采集流程实操:手把手教你跑一次
好,理论说完了,咱们动手。假设你要分析一个PyTorch训练脚本:
# 1. 启动Nsight Systems
nsys profile -o my_trace -t cuda,nvtx,osrt \
--capture-range=cudaProfilerApi \
--gpu-metrics-devices=0 \
python train.py
# 2. 在代码中标记关键区域
import nvtx
with nvtx.annotate("forward_pass", color="green"):
output = model(input)
with nvtx.annotate("backward_pass", color="red"):
loss.backward()
# 3. 手动控制采集范围
cuda.cudart().cudaProfilerStart()
# ... 你的核心代码 ...
cuda.cudart().cudaProfilerStop()
跑完之后,你会得到一个 my_trace.nsys-rep 文件。用Nsight Systems打开,就能看到完整的时间线了。
小技巧:我习惯在代码里加NVTX标记,把前向、反向、优化器更新、数据加载都标上不同颜色。这样在Trace里一眼就能看出每个阶段花了多少时间,比事后猜要准得多。
4.4 采集文件管理:别让数据变成垃圾
Trace文件有个特点:大。一次Full Trace轻松上GB,跑10次就是10GB。怎么管?
4.4.1 文件命名规范
我建议用这个格式:
{项目名}_{场景}_{日期}_{版本}.nsys-rep
比如:resnet50_training_20250115_v2.nsys-rep
别用「final」「最终版」这种名字——你懂的,永远有下一个版本。
4.4.2 文件压缩与归档
Nsight支持导出为压缩格式:
nsys stats my_trace.nsys-rep -o my_trace.csv
nsys export my_trace.nsys-rep -o my_trace.json
CSV和JSON可以压缩到原来的1/10,方便存档和分享。
4.4.3 版本对比
优化前后,一定要保留两份Trace。我习惯在文件名里加 _baseline 和 _optimized 后缀。Nsight支持直接对比两个Trace文件,能自动算出加速比。
我的经验:Trace文件不是越多越好。每次采集前,先问自己三个问题:
- 我要验证什么假设?
- 这次采集和上次有什么不同?
- 这个文件以后还用得上吗?
回答清楚了再动手。否则,你只是在制造数据垃圾。
4.5 知识体系一览
下面这张图,是我自己总结的Trace采集知识框架。建议你收藏,每次采集前扫一眼:
这张图把Trace采集拆成了四个维度。每次采集前,对照着检查一遍:概念理解了吗?配置调了吗?流程走对了吗?文件存好了吗?
最后说一句:Trace采集不是一次性的活。我通常的做法是:先跑一次Full Trace摸清全貌,然后针对瓶颈区域做Range Trace深入分析。优化完再跑一次Full Trace验证效果。如此循环,直到性能达标。
好了,Trace采集就讲到这里。记住,工具再好,也得会用、用对。下次你遇到GPU性能问题,别急着改代码,先开Trace看看——答案往往就在时间线上。