| name | tilelang-cuda-optimization |
| description | TileLang CUDA 性能优化通用策略、最佳实践和调试技巧汇总。适用于需要提升 TileLang 内核性能、遇到编译/运行错误需要排查、或需要了解 TileLang 平台限制的内核代码生成和优化场景 |
| category | method |
| version | 1.0.0 |
| metadata | {"backend":"cuda","dsl":"tilelang_cuda"} |
| structure | {"child_skills":["tilelang-cuda-memory","tilelang-cuda-synchronization"]} |
TileLang CUDA 性能优化指南
1. 性能优化策略
1.1 分块大小选择
- 原则: 平衡并行度与资源占用
- 建议: 使用 2 的幂次
- 常用值: block_M/block_N = 64, 128, 256; block_K = 16, 32, 64
| 算子类型 | 推荐分块大小 | 线程数 |
|---|
| Element-wise | block = 256-1024 | 128-256 |
| GEMM | block_M=128, block_N=128, block_K=32 | 128 |
| Reduce | block = 256-512 | 128-256 |
1.2 软件流水线优化
def pipelined_computation():
num_stages = 3
for ko in T.Pipelined(T.ceildiv(K, block_K), num_stages=num_stages):
T.copy(A[by * block_M, ko * block_K], A_shared)
T.copy(B[ko * block_K, bx * block_N], B_shared)
T.gemm(A_shared, B_shared, C_local)
流水线深度选择:
num_stages=2: 最少的共享内存使用
num_stages=3: 通常最优(推荐默认值)
num_stages=4: 更多重叠但占用更多共享内存
num_stages=5+: 可能超出共享内存限制
1.3 并行化策略
for i, j in T.Parallel(block_M, block_N):
pass
for k in T.vectorized(TILE_K):
A_local[k] = A[bk * BLOCK_K + tk * TILE_K + k]
for k in T.serial(block_K):
pass
1.4 数据类型优化
input_dtype = "float16"
accum_dtype = "float"
result = A[i].astype(accum_dtype) * B[i].astype(accum_dtype)
2. 内存优化策略
2.1 内存层次结构优化
def memory_optimized_matmul(M, N, K, block_M, block_N, block_K):
@T.prim_func
def main(A: T.Tensor((M, K), "float16"),
B: T.Tensor((K, N), "float16"),
C: T.Tensor((M, N), "float16")):
with T.Kernel(T.ceildiv(N, block_N), T.ceildiv(M, block_M), threads=128) as (bx, by):
A_shared = T.alloc_shared((block_M, block_K), "float16")
B_shared = T.alloc_shared((block_K, block_N), "float16")
C_local = T.alloc_fragment((block_M, block_N), "float")
T.use_swizzle(panel_size=10, enable=True)
T.clear(C_local)
for ko in T.Pipelined(T.ceildiv(K, block_K), num_stages=3):
T.copy(A[by * block_M, ko * block_K], A_shared)
T.copy(B[ko * block_K, bx * block_N], B_shared)
T.gemm(A_shared, B_shared, C_local)
T.copy(C_local, C[by * block_M, bx * block_N])
return main
2.2 内存访问模式优化
for k in T.vectorized(TILE_K):
A_local[k] = A[bk * BLOCK_K + tk * TILE_K + k]
T.copy(A[start:end], A_shared)
from tilelang.intrinsics import make_mma_swizzle_layout
T.annotate_layout({
A_shared: make_mma_swizzle_layout(A_shared),
B_shared: make_mma_swizzle_layout(B_shared),
})
2.3 L2 缓存优化
T.use_swizzle(panel_size=10, enable=True)
3. 同步安全优化
3.1 使用内置归约函数(强烈推荐)
T.reduce_sum(input_tensor, output_tensor, dim=axis)
T.reduce_max(input_tensor, output_tensor, dim=axis)
T.reduce_min(input_tensor, output_tensor, dim=axis)
T.reduce_mean(input_tensor, output_tensor, dim=axis)
3.2 避免手动归约
while stride > 0:
if tid < stride:
shared[tid] += shared[tid + stride]
T.sync_threads()
stride //= 2
T.reduce_sum(input, output, dim=1)
3.3 推荐的并行计算模式
for i, j in T.Parallel(M, N):
result[i, j] = input[i, j] * scale[i]
for i in T.vectorized(N):
result[i] = input[i] * scale
for k in T.Pipelined(K, num_stages=3):
T.copy(A[k], shared_A)
T.gemm(shared_A, shared_B, result)
4. 数值稳定性
4.1 防溢出处理
T.fill(scores_max, -T.infinity("float"))
T.reduce_max(acc_s, scores_max, dim=1)
for i, j in T.Parallel(block_M, block_N):
acc_s[i, j] = T.exp2(acc_s[i, j] * scale - scores_max[i] * scale)
4.2 精度提升
- 使用 float32 进行累加: 即使输入是 float16/bfloat16
- 最后再转换: 计算完成后再转回目标精度
C_local = T.alloc_fragment((block_M, block_N), "float")
result = C_local.astype("float16")
5. 性能检查清单
内存访问
并行度配置
计算优化
安全性
数值稳定性
6. 常见性能陷阱
- 过度分块: 过小的 tile 导致内存访问效率低
- 流水线深度不当: 过深或过浅的流水线影响性能
- 内存银行冲突: 共享内存访问模式不当
- 类型转换开销: 频繁的类型转换影响性能
- 同步开销: 不必要的线程同步
- 同步死锁: 条件分支中的同步导致线程卡死
- 线程索引错误: 使用错误的线程索引获取方式
- 共享内存分配错误: 在条件分支中分配共享内存
最佳实践总结
- 先正确性后性能: 确保内核正确性后再优化性能
- 内存优先: 优先优化内存访问模式
- 同步安全: 严格遵循同步使用规范,避免死锁
- 使用内置原语: 优先使用 T.gemm、T.reduce_* 等内置函数
- 混合精度: 输入用低精度,累加用高精度
- 流水线: 通过 T.Pipelined 隐藏内存延迟