Triton源码目录:打开Triton源码的正确姿势:从一头雾水到心里有数
你有没有过这种经历——听说Triton写GPU Kernel很香,兴冲冲git clone下来,然后打开文件夹就懵了:include/、lib/、Dialect/、Conversion/……一堆目录扑面而来,根本不知道从哪下手。
反正我有。第一次看Triton源码的时候,光目录结构就研究了半天,最后硬着头皮一个个文件点开看,效率低得令人发指。
后来跟着刘灿老师的分享系统地梳理了一遍,才算把Triton的源码骨架理清楚。这篇文章就是我当时的学习笔记,希望能帮你少走点弯路。
本文基于 triton-lang/triton 仓库(https://github.com/triton-lang/triton),以 PPT 内容为主线整理。
先看全景:四大核心目录
打开Triton仓库,你最先需要关注的是这四个目录:
别被其他目录分散注意力,include/、lib/、python/、runtime/这四个才是主干。其中include/和lib/又是理解编译流程的重中之重——它们承载了Triton基于MLIR构建的整个编译管线。
include 和 lib:MLIR世界的"C头文件"和"实现"
include/ 里有什么?
Triton在MLIR框架上定义了两个核心Dialect:
- Triton Dialect:高层、设备无关的IR。你写的
tt.load、tt.store、tt.dot最终都会落到这个Dialect里。 - TritonGPU Dialect:GPU相关的抽象,引入了Layout概念(Blocked、MMA、Slice、Shared等),决定了数据在GPU线程和内存中的分布方式。
include/下面主要就是这两个Dialect的Op定义(TableGen .td文件)、类型定义和属性定义。
lib/ 里有什么?
lib/是include/的对应实现,包括:
| 子目录 | 作用 |
|---|---|
lib/Dialect/Triton/ | Triton Dialect的IR实现 + 优化Pass |
lib/Dialect/TritonGPU/ | TritonGPU Dialect的IR实现 + 大量优化Pass |
lib/Conversion/ | Dialect之间的转换(降级)逻辑 |
lib/Target/ | 最终代码生成(LLVM IR → PTX / ROCm) |
简单粗暴地记:include定义"是什么",lib实现"怎么做"。
Dialect 目录:Triton编译器的灵魂
理解Dialect是理解Triton源码的关键。Triton的编译流程本质上就是Dialect的逐级降级:
Triton Dialect ──→ TritonGPU Dialect ──→ LLVM Dialect ──→ 机器码 (高层语义) (GPU映射) (通用IR) (PTX/ROCm)为什么要分两个Dialect?这是MLIR框架的精髓——分层抽象:
- Triton Dialect完全不关心GPU硬件细节,只描述"做什么计算"(load、store、dot、reduce……)
- TritonGPU Dialect负责把计算映射到具体的GPU执行单元上——数据怎么分配到warp、怎么用Tensor Core、shared memory怎么管理
这种设计让前端(Python DSL)和后端(各种GPU)可以独立演进,互不干扰。
编译流程对应源码位置:一张图搞定
这是整份PPT里信息密度最高的一页:
把Triton的编译流程和源码目录对应起来,就长这样:
| 编译阶段 | 源码位置 | 做了什么 |
|---|---|---|
| Triton IR | lib/Dialect/Triton/ | 定义高层Op语义,执行通用优化 |
| Triton → TritonGPU | lib/Conversion/TritonToTritonGPU/ | 引入GPU Layout,分配warp |
| TritonGPU 优化 | lib/Dialect/TritonGPU/ | coalesce、pipeline、prefetch等大量GPU优化 |
| TritonGPU → LLVM | lib/Conversion/TritonGPUToLLVM/ | MMA lowering、shared memory处理 |
| LLVM → 目标代码 | lib/Target/LLVMIR/ | 生成LLVM IR,后面交给LLVM后端生成PTX |
如果你想跟踪一个triton.dot操作从Python一路变成PTX指令的全过程,顺着这个表找对应文件就行。
常用文件速查手册
Triton Dialect 核心文件
Op定义:/include/triton/Dialect/Triton/IR/TritonOps.td
这里定义了你在Python里调用的所有基础操作:
tt.call、tt.func、tt.return—— 函数调用机制tt.load、tt.store—— 全局内存读写tt.dot—— 矩阵乘法,Triton的招牌操作
优化Pass:/lib/Dialect/Triton/Transforms/
包含CombineOpsPass、ReorderBroadcastPass、RewriteTensorPointerPass、LoopUnrollPass等。这些Pass在GPU无关的层面做图优化——算子融合、死代码消除、循环展开,跟传统编译器优化的套路差不多。
Triton → TritonGPU 转换:lib/Conversion/TritonToTritonGPU/TritonToTritonGPUPass.cpp
这是整个编译流程的第一个"硬核跳变"。在这里,设备无关的Triton IR被注入GPU-specific的Layout信息——数据开始被分配到具体的线程和内存层级。
TritonGPU Dialect 核心文件
Op定义:/include/triton/Dialect/TritonGPU/IR/TritonGPUOps.td
GPU特有的操作:async_wait、alloc_tensor、insert_slice_async、convert_layout。
Layout属性定义:/include/triton/Dialect/TritonGPU/IR/TritonGPUAttrDefs.td
这是TritonGPU最核心的设计——五种Layout:
| Layout | 含义 |
|---|---|
| Blocked | 数据按块分配给线程,最通用 |
| MMA | 为Tensor Core矩阵乘累加定制 |
| DotOperand | dot操作的输入数据布局 |
| Slice | 数据切片后的布局 |
| Shared | shared memory中的数据布局 |
优化Pass:/lib/Dialect/TritonGPU/Transforms/
这里有一大堆GPU专用Pass,每个都值得单独写一篇文章:
AccelerateMatmul—— 把普通矩阵乘匹配到Tensor Core指令Pipeline/Prefetch—— 指令流水线和数据预取,Triton性能的核心来源Coalesce—— 合并内存访问,减少bank conflictRemoveLayoutConversions—— 消除不必要的layout转换开销OptimizeThreadLocality—— 优化线程局部性AllocateSharedMemoryPass—— shared memory分配
补充说明:
Pipeline和Prefetch是Triton自动生成异步拷贝流水线的关键实现。它们会在循环内插入cp_async指令,让数据搬运和计算重叠执行——这正是Triton Kernel经常能追平甚至超过手写CUDA的原因。
一句话总结
Triton的源码结构本质上就是一条MLIR编译管线:
include/ (定义) → lib/Dialect/ (IR实现) → lib/Conversion/ (Dialect降级) → lib/Target/ (代码生成)如果你也想入手Triton源码,我的建议是:
- 先看
include/triton/Dialect/Triton/IR/TritonOps.td,搞清楚Triton有哪些基础操作 - 跟踪
triton.dot从 Triton Dialect → TritonGPU → LLVM 的完整降级路径 - 用
mlir-opt --print-ir-before-all实际跑一遍 Pass Pipeline,直观感受每个Pass的效果
源码链接:https://github.com/triton-lang/triton
本文内容整理自先进编译实验室刘灿的分享,感谢。
