必须指定record_shapes=True才能看清张量维度变化,否则shape列全为空,无法区分大张量运算与标量操作;需配合schedule(wait=1,warmup=1,active=3)精准捕获稳定态,启用Group by Operator并按Self CPU time排序分析算子本体耗时。

Profiler 启动时必须指定 record_shapes=True 才能看清张量维度变化
默认情况下 torch.profiler.profile 不记录张量 shape 和 dtype,导致你看到 aten::add 却不知道是 2GB 的大 tensor 还是标量加法。这会让「哪个算子吃内存/耗时」完全无法定位。
实操建议:
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 始终显式传参:
record_shapes=True(否则 profile 报告里 shape 列全为空) - 搭配
with_flops=True可估算理论计算量,辅助判断是否算力未打满 - 如果只关心 CPU 时间,加上
profile_memory=False能显著降低开销(尤其在大模型上)
用 schedule 参数控制 profiling 范围,避免全 epoch 跑满才出报告
直接对整个训练循环跑 profile,结果会被前几轮 warmup 和后几轮收敛阶段污染,关键瓶颈反而被平均掉。更糟的是,profiler 默认会记录全部 step,内存暴涨甚至 OOM。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
torch.profiler.schedule(wait=1, warmup=1, active=3):跳过第 0 步(wait),第 1 步热身(warmup),只精准采集第 2–4 步(active) -
wait和warmup都设为 0 会导致首次执行被计入统计,而 CUDA kernel 尚未预热,时间严重失真 - 配合
on_trace_ready回调,每轮 active 结束立即保存trace.json,方便 Chrome Tracing 查看
Chrome Trace 分析时重点关注 self_cpu_time_total 和 categorized by operator
打开 trace.json 后,默认视图容易误读「总耗时最长」的节点——比如 cudaStreamSynchronize 排第一,但它只是等待信号,真正瓶颈在它前面那个没同步完的 kernel。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 在 Chrome Tracing 界面右上角点「View Options」→ 勾选「Group by Operator」,立刻按算子聚合,
aten::matmul、aten::conv2d的真实占比一目了然 - 排序列选
Self CPU time (us)(不是 Total),排除调用开销干扰,专注算子本体 - 若发现大量
aten::empty或aten::copy_占比高,大概率是频繁新建 tensor 或跨 device 拷贝(检查.to(device)是否写在循环里)
profile_memory=True 时注意 GPU memory usage 曲线和 allocation 事件的区别
profile_memory=True 会开启内存追踪,但报告里同时存在「GPU 内存占用峰值」和「单次 allocation 大小」两类数据,新手常把二者混淆。前者决定 OOM 风险,后者反映碎片或冗余分配。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 看 Summary 表格中的
allocated memory(累计分配量)和reserved memory(PyTorch 缓存池大小),若 reserved 远大于 allocated,说明缓存没释放或存在 memory leak - 在 Events 视图中过滤
Memory类型,找连续多次cudaMallocAsync+ 小间隔cudaFreeAsync,典型特征是「反复申请释放同尺寸 tensor」,应复用 buffer - 避免在
forward中用torch.zeros(..., device='cuda'),改用torch.empty(..., device='cuda').zero_()减少初始化开销


















