Triton调试:Triton调试从入门到裂开再到起飞:一套工具链吃透MLIR全流程
写Triton kernel最崩溃的不是算法写不对——是编译出来结果错了、精度炸了、性能崩了而你盯着满屏Python traceback一脸懵“IR到底在哪一层出了问题”这事我踩过太多坑了。跑一个matmulautotune选出来的配置是快了但结果错的。加了个tl.dotCUDA报错misaligned address。不是说Triton是写起来像Python、跑起来像CUDA吗那调试为什么像拆盲盒别急。本文基于杜玉博老师的分享系统梳理Triton调试的完整工具链——从标准的PDB/GDB到官方环境变量三板斧再到MLIR层面的triton-opt和triton-translate让你在每一层IR都能精准定位问题。一、先别急着掏MLIRPython/C层面的基础调试很多人一上来就想dump IR但往往问题出在Python层或是C runtime层。基础工具能解决的就别上大炮。1.1 PDBPython kernel调试PDB是Python内置的调试器不需要安装任何东西。当你怀疑是kernel参数传错、grid配置不对、或者自动微分出了问题PDB就是第一选择。常用PDB命令命令作用b 行号在指定行设置断点c继续执行到下一个断点n逐行执行不进入函数内部s步入函数内部p 变量名打印变量值l查看当前行附近的代码q退出调试用法很简单在你想打断点的地方插入一行importpdb;pdb.set_trace()或者启动时直接python-mpdb your_triton_script.py1.2 GDB当问题沉到C层Triton编译流程走到后面全是C——MLIR的Pass、LLVM的codegen、ptxas的汇编。这时候PDB就管不到了得上GDB。关键差别记牢了PDB用Python写的kernel逻辑调试断点打在triton.jit装饰的函数里GDB调试Triton编译器的C代码断点打在lib/Conversion/、lib/Dialect/等源码路径用GDB调试Triton程序的启动方式# Triton程序本质是python脚本所以要这样起gdb-argspython your_script.py进GDB后(gdb) b TritonToTritonGPUPass.cpp:123 # 在某个Pass的特定行打断点 (gdb) r # 运行 (gdb) bt # 崩溃了看调用栈 (gdb) p *someValue # 查看变量二、理解Triton编译流水线你不知道数据流经了哪些层怎么定位调试之前必须搞清楚Triton代码到底走过了哪些阶段。否则dump出来的IR你看都看不懂。Triton的编译架构分三大块Frontend Optimizer Backend ┌─────────┐ ┌──────────────┐ ┌──────────────┐ │ Python │ → │ Triton IR │ → │ LLVM IR │ │ Kernel │ │ → TTGIR │ │ → PTX │ │ Code │ │ (各种Pass) │ │ → cubin │ └─────────┘ └──────────────┘ └──────────────┘Frontend把你写的triton.jitPython代码转成Triton IR.ttir同时负责kernel launch的runtime逻辑Optimizer通过一系列MLIR Pass把Triton IR逐步转换为TritonGPU IR.ttgir——这里会做shared memory分配、warp调度、coalesce等优化Backend把TritonGPU IR转成LLVM IR.llir最后通过ptxas编译成GPU能执行的cubin问题往往出在Optimizer和Backend的交界处你的算法逻辑是对的但某个Pass把memory layout搞乱了或者thread placement不合理。下面就是对付这种场景的武器。三、环境变量三连不写一行代码就能dump全流程IRTriton官方提供了几个环境变量设了就自动dump IR。不需要改任何代码。3.1MLIR_ENABLE_DUMP1这个可能是最常用的调试手段。设了这个变量后Triton会在每个MLIR Pass前后自动把IR打印到终端。MLIR_ENABLE_DUMP1python your_triton_script.py你能看到类似这样的输出流// *** IR Dump Before TritonToTritonGPUPass *** tt.func kernel(...) { ... } // *** IR Dump After TritonToTritonGPUPass *** ttg.func kernel(...) { ... }⚠️ 一个坑如果设了环境变量但没看到输出先清理triton cacherm-rf~/.triton/cache3.2LLVM_IR_ENABLE_DUMP1类似上面但在LLVM IR层面打印每个pass前后的IR。当你怀疑是LLVM codegen出了问题比如地址计算错误、向量化异常用这个。LLVM_IR_ENABLE_DUMP1python your_triton_script.py3.3TRITON_PRINT_AUTOTUNING1这个不是用来debug correctness的而是用于性能调优。autotune选出来一堆配置想知道哪个最优、耗时多少TRITON_PRINT_AUTOTUNING1python your_triton_script.py输出类似Triton Autotuning: best config {BLOCK_M: 128, BLOCK_N: 128, ...}, time 12.3 us四、triton-opt逐Pass拆解IR变换的显微镜环境变量dump的是全量流水线信息太多容易看花眼。当你想精细控制某个特定Pass的输入输出时就要用triton-opt。triton-opt是Triton源码编译后产出的工具需要先把它的路径加到环境变量里。它的核心用法是接收一个IR文件跑指定的Pass输出变换后的IR文件。基本用法# .ttir → .ttgirTriton IR 降级到 TritonGPU IRtriton-opt XX.ttir -convert-triton-to-tritongpuXX.ttgir# 在 .ttgir 层面执行特定优化triton-opt XX.ttgir --tritongpu-coalesce --tritongpu-pipelineXX-opt.ttgir配合GDB使用才是完全体gdb triton-opt(gdb)b TritonToTritonGPUPass.cpp:123(gdb)r XX.ttir -convert-triton-to-tritongpuXX.ttgir这样你可以在特定Pass的C源码中打断点配合输入IR和输出IR做对比分析。实战场景分阶段lowering定位bug这是最有效的方法——不要一次跑完整个pipeline分阶段来# 第一步Triton IR → TritonGPU IRtriton-opt model.ttir -convert-triton-to-tritongpu-omodel.ttgir# 第二步TritonGPU IR → LLVM IRtriton-opt model.ttgir -convert-tritongpu-to-llvm-omodel.llir哪一步输出的IR不对问题就在那一步。五、triton-translate从IR到PTX的最后一公里triton-translate的职责是把MLIR转换成最终的可执行产物——PTX或LLVM IR。它在pipeline中处于最末端。# ttgir → llirtriton-translate XX.ttgir--targetllvmirXX.llir# ttgir → ptx如果需要直接看PTX汇编triton-translate XX.ttgir --mlir-to-ptx-oXX.ptx同样配合GDBgdb triton-translate(gdb)b SomeBackendPass.cpp:456(gdb)r XX.ttgir--targetllvmirXX.llirtriton-translate和triton-opt的关系简单说triton-opt管IR的变换优化Passtriton-translate管IR到目标代码的翻译六、实战推荐组合根据问题类型我整理了以下调试策略问题现象首选工具策略Python层报错、参数问题PDBimport pdb; pdb.set_trace()编译时crash、C segfaultGDB MLIR_ENABLE_DUMP先设环境变量看crash在哪个pass然后GDB打断点结果数值不对MLIR_ENABLE_DUMPdump全量IR找关键optt.dot、tt.load的数值性能不达预期triton-opt 分阶段看ttgir层的shared memory layout和coalescePTX生成异常triton-translate直接看生成的PTX是否符合预期autotune选配置不满意TRITON_PRINT_AUTOTUNING打印所有候选配置及耗时终极组合技# 先dump全量IR看问题在哪一层MLIR_ENABLE_DUMP1python your_script.py21|grep-A50error\|warning\|misaligned# 定位到具体pass后用triton-opt精细调试triton-opt model.ttir -convert-triton-to-tritongpu -mlir-print-ir-after-alldebug.log# 在关键pass打断点gdb triton-opt(gdb)b problematic_pass.cpp:xxx(gdb)r model.ttir -convert-triton-to-tritongpu七、总结Triton调试的核心思路就一句话分层定位逐级缩小。不要一上来就盯着MLIR看——先从Python层排除参数问题、再从autotune排除配置问题、然后用环境变量dump IR定位到具体Pass、最后用triton-opt/triton-translate精细拆解。工具都在这里了下次跑Triton kernel出问题的时候别再只会print了。本文整理自杜玉博老师的《Triton调试方法及工具》分享结合个人实战经验补充了大量操作细节和避坑指南。官方文档参考Triton - Tips for Hacking