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文件不是越多越好。每次采集前,先问自己三个问题:

  1. 我要验证什么假设?
  2. 这次采集和上次有什么不同?
  3. 这个文件以后还用得上吗?

回答清楚了再动手。否则,你只是在制造数据垃圾。

4.5 知识体系一览

下面这张图,是我自己总结的Trace采集知识框架。建议你收藏,每次采集前扫一眼:

Trace采集 概念 采集配置 实操流程 时间戳 事件类型 上下文信息 采集模式 Buffer Size Kernel Sampling 命令行采集 NVTX标记 手动控制范围 命名规范 压缩归档 版本对比 Trace采集知识体系框架

这张图把Trace采集拆成了四个维度。每次采集前,对照着检查一遍:概念理解了吗?配置调了吗?流程走对了吗?文件存好了吗?

最后说一句:Trace采集不是一次性的活。我通常的做法是:先跑一次Full Trace摸清全貌,然后针对瓶颈区域做Range Trace深入分析。优化完再跑一次Full Trace验证效果。如此循环,直到性能达标。

好了,Trace采集就讲到这里。记住,工具再好,也得会用、用对。下次你遇到GPU性能问题,别急着改代码,先开Trace看看——答案往往就在时间线上。