PyTorch TorchInductor 溯源追踪(Provenance Tracking)实战指南:从计算图到生成内核的可视化映射
【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch
导读
torch.compile会把一个 Python 模型依次经历 pre-grad 图、post-grad 图,最终由 TorchInductor(或 AOTInductor)生成 Triton/C++ 内核,中间经过了大量 pass 的变换,普通开发者很难把最终生成的内核与最初的算子对应起来。本文基于 PyTorch 官方文档中的 Provenance Tracking(溯源追踪)章节,结合本仓库源码,讲解如何通过tlparse工具将「输入 GraphModule → post-grad 图 → Inductor 生成代码」三段之间的映射关系可视化,并逐内核查看其对应的源码与调试句柄(debug handle)。读完本文,你将掌握INDUCTOR_PROVENANCE=1环境变量的完整用法、tlparse --inductor-provenance的输出解读,以及映射数据在 torch/_inductor/debug.py 与 torch/_inductor/compile_fx.py 中的产生原理。
什么是 Inductor 溯源追踪
溯源追踪(Provenance Tracking)是 PyTorch 编译栈中面向调试与性能分析的一项功能,服务于 TorchInductor 与 AOTInductor 两条编译路径。其核心能力是:可视化输入 GraphModule(编译前计算图)与优化后生成代码之间的对应关系,让你能够追踪原始算子在整个编译过程中被如何变换、融合成最终的内核。
工具界面将信息划分为三个面板:
- panel 1:输入 GraphModule 中的节点(pre-grad 图);
- panel 2:post-grad 图(梯度计算完成之后、Inductor 调度之前的图)中的节点;
- panel 3:Inductor 生成的代码(wrapper 代码与内核源码)。
面板中加粗的行表示当前溯源追踪功能已覆盖的节点/内核。目前覆盖的内核类型包括Triton 内核、C++(cpp)内核与组合内核(combo kernels);黄色高亮则显示该节点/内核的溯源(provenance)归属。
以下为 TorchInductor 路径下溯源追踪工具的运行效果截图:
以下为 AOTInductor(aot_compile 部署路径)下的运行效果:
使用溯源高亮器(Provenance Tracking Highlighter)
启用并使用溯源追踪功能,只需三步:安装tlparse、以指定环境变量运行程序、对日志运行tlparse。
第一步:安装 tlparse
tlparse是一个用 Rust 编写的日志解析与可视化工具,通过 Cargo 安装:
cargo install tlparse如果环境中还没有cargo(Rust 工具链),需要先安装 Rust/Cargo(参见 Cargo Book 的安装章节,本文不再赘述)。
第二步:以溯源追踪模式运行程序
在运行 PyTorch 程序时设置两个环境变量:
TORCH_TRACE=~/my_trace_log_dir INDUCTOR_PROVENANCE=1 python your_program.pyTORCH_TRACE=~/my_trace_log_dir:指定 trace 日志输出目录;INDUCTOR_PROVENANCE=1:开启 Inductor 层面的溯源追踪。
运行结束后,~/my_trace_log_dir下会生成日志文件,该日志将被tlparse用于生成溯源追踪高亮器。
第三步:运行 tlparse 生成可视化
对日志文件直接运行tlparse,并带上--inductor-provenance标志:
tlparse log_file_name.log --inductor-provenance运行完成后,在tlparse的输出中会出现一个额外的"Provenance Tracking"(溯源追踪)区块,点击其中的链接即可进入溯源追踪工具界面。
使用要点与注意事项
不加标志也能看到 JSON 映射:即使不加
--inductor-provenance标志,在tlparse输出的index.html中,inductor_provenance_tracking_node_mappings_<number>.json文件里依然可以看到节点映射的 JSON 数据。直接对日志文件运行 tlparse:请直接对 log 文件执行
tlparse log_file_name.log --inductor-provenance;直接对文件夹运行tlparse parse <folder_name> --inductor-provenance可能无法正常工作。溯源高亮器依赖的工件(artifacts):该功能依赖以下由 PyTorch 编译过程产生的文件:
工件文件名 内容 before_pre_grad_graph.txtpre-grad(输入)图文本 after_post_grad_graph.txtpost-grad 图文本 inductor_aot_wrapper_code.txtAOT wrapper 代码 inductor_output_code.txtInductor 最终生成的输出代码 inductor_provenance_tracking_node_mappings.json节点映射数据(内核 ↔ post-grad ↔ pre-grad)
以下为 tlparse 输出中 "Provenance Tracking" 区块入口的示意图:
溯源追踪的源码实现原理
仅仅会使用还不够,理解映射数据从何而来,能帮助你在数据异常时快速定位问题。溯源追踪的开关与参数集中在 torch/_inductor/config.py 的trace配置中:
# torch/_inductor/config.py # Save mapping info from inductor generated kernel to post_grad/pre_grad fx nodes # Levels: # 0 - disabled (default) # 1 - normal # 2 - basic # Backward compatibility: # If TORCH_COMPILE_DEBUG=1, level is set to at least 1. # If INDUCTOR_PROVENANCE is set, use its integer value. provenance_tracking_level: int = int( os.environ.get( "INDUCTOR_PROVENANCE", os.environ.get("TORCH_COMPILE_DEBUG", "0") ) )关键点:
- 级别语义:
provenance_tracking_level支持0(默认关闭)、1(normal)、2(basic)三档; - 向后兼容:设置
TORCH_COMPILE_DEBUG=1时级别至少提升为1;若同时设置INDUCTOR_PROVENANCE,则以其整数值为准。effective_provenance_tracking_level()(见 config.py)统一了这一逻辑——当TORCH_COMPILE_DEBUG_EXTEND=1(将内核栈回溯写回 profiler timeline)时,级别会被强制提升到至少 1。 - 防 OOM 保护:
provenance_tracking_max_events(环境变量TORCH_COMPILE_DEBUG_MAX_EVENTS,默认 500000)限制了 profiler timeline 后处理阶段处理的 trace 事件数量,超过上限即跳过溯源以避免内存溢出。
映射数据的采集与序列化实现在 torch/_inductor/debug.py:
- 全局状态:
_inductor_post_to_pre_grad_nodes、_inductor_triton_kernel_to_post_grad_node_info、_inductor_kernel_stack_trace等模块级字典(debug.py)在编译期间持续累积映射关系;reset_provenance_globals()上下文管理器(debug.py)保证每次编译之间状态被正确重置与恢复。 - 内核级采集:
set_kernel_post_grad_provenance_tracing()(debug.py)为每个生成的内核建立与 post-grad 节点的映射:对调度节点,通过 IR 节点上的origins(哪些 FX IR 节点贡献了该融合内核)与更精确的origin_node(内容与某个 FX 节点输出完全对应)收集来源;同时收集内核的栈回溯(stack traces)。该函数还会返回一个自增的整数 debug handle,用于区分同一内核的多次调用。 - JSON 落盘:
dump_inductor_provenance_info()(debug.py)在 trace 开启时把合并后的映射写入inductor_provenance_tracking_node_mappings.json,并写入"version": 2.0字段,供 tlparse 识别当前映射格式版本。异常会被signpost_event记录,而绝不会影响正常程序执行——这也是整个溯源功能的设计原则。 - 编译入口:在 torch/_inductor/compile_fx.py 中,
before_pre_grad_graph(compile_fx.py 附近)与after_post_grad_graph文本被保存,inductor_provenance_tracking_node_mappings与inductor_provenance_tracking_kernel_stack_traces两个工件在 compile_fx.py 附近按effective_provenance_tracking_level() != 0的条件打包进 trace 工件中。 - 输出代码中的溯源信息:在 torch/_inductor/output_code.py 中,
OutputCode类带有inductor_provenance_mapping_str与inductor_provenance_stack_traces_str两个字段(output_code.py),说明生成代码与映射/栈回溯信息是绑定在一起的。
查看每个 Inductor 内核对应的源码
启用INDUCTOR_PROVENANCE=1之后,你还可以在 tlparse 中查看每个 Inductor 内核对应的源码。
在 tlparse 输出中找到inductor_provenance_tracking_kernel_stack_traces.json,点击其旁边的"readable_html"链接即可进入内核源码查看页面。
理解内核名称中的 debug handle
在内核源码视图中,内核名称末尾常带有形如:1、:467的后缀,例如:
triton_per_fused_add_1triton_per_fused_add_467
这些后缀用于区分同一内核被多次调用的情况,官方称之为debug handles(调试句柄)。在源码实现中,正是set_kernel_post_grad_provenance_tracing()通过全局计数器_inductor_kernel_provenance_debug_handle为每个内核追加:{n}后缀(见 debug.py),从而为每一次内核生成调用建立唯一标识。
另外,在内核源码的注释中也能找到对应的 debug handle,方便你在生成代码与追踪数据之间来回核对:
典型排查场景
溯源追踪在以下场景中尤为实用:
- 算子消失了?:训练/推理脚本中写了某个算子,但生成的 CUDA 内核里找不到——通过溯源高亮可以看到该节点是否被常量折叠、被其他内核融合,或在某个 pass 中被替换;
- 性能归属:分析 Inductor 生成的 Triton 内核分别对应计算图的哪些算子,从而定位某个“意外变慢”的算子最终被并入了哪个内核;
- AOT 部署对比:
torch._export.aot_compile导出的 AOTInductor 模型与 JIT 编译路径生成的内核差异,可通过三面板映射直观对比。
延伸阅读
tlparse是 Rust 编写的独立工具,本仓库通过INDUCTOR_PROVENANCE等环境变量与其对接;相关排查指南见 torch.compiler_troubleshooting。- 若想深入源码,可依次阅读 torch/_inductor/config.py(开关与级别)、torch/_inductor/debug.py(映射采集与落盘)、torch/_inductor/compile_fx.py(工件生成时机)与 torch/_inductor/output_code.py(内核代码与溯源信息的绑定)。
- 溯源追踪依赖
TORCH_TRACE的 trace 日志机制,其更多用法可参考 torch.compiler_profiling_torch_compile。
【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考