Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/mindspore-ai/akg --skill tilelang-cuda-basics명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | tilelang-cuda-basics |
| description | TileLang CUDA 核心概念、内核结构和标准编程模式 |
| category | fundamental |
| version | 1.0.0 |
| metadata | {"backend":"cuda","dsl":"tilelang_cuda","operator_patterns":"all"} |
@tilelang.jit 装饰的函数,编译后在 GPU 上并行执行@T.prim_func 装饰的主函数,通过 T.Kernel 上下文管理器定义并行执行逻辑T.ceildiv 计算块数threads 参数设置T.Kernel 上下文返回 (bx, by) 对应 blockIdx.x, blockIdx.yT.alloc_shared 分配T.alloc_fragment 分配T.alloc_local 分配TileLang 内核的标准结构模式:
import tilelang
import tilelang.language as T
@tilelang.jit(out_idx=[-1])
def my_kernel(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")):
# 1. 定义内核上下文(网格和线程配置)
with T.Kernel(T.ceildiv(N, block_N), T.ceildiv(M, block_M), threads=128) as (bx, by):
# 2. 内存分配
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")
# 3. 初始化
T.clear(C_local)
# 4. 计算逻辑(含数据加载和计算)
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)
# 5. 结果写回
T.copy(C_local, C[by * block_M, bx * block_N])
return main
TileLang 的 @tilelang.jit / tilelang.compile 通过 out_idx 指定哪些张量属于输出。
@tilelang.jit(out_idx=[1])
def parallel_elementwise_static(length=256):
@T.prim_func
def main(A: T.Tensor((length,), "float32"),
B: T.Tensor((length,), "float32")):
with T.Kernel(1, threads=length) as _:
for i in T.Parallel(length):
B[i] = A[i] + 1.0
return main
kernel = parallel_elementwise_static()
result = kernel(data) # ✅ 只传输入 data;TileLang 根据 out_idx 返回输出
out_idx=[-1]: 最后一个张量为输出out_idx=[1]: 第二个张量为输出out1, out2 = kernel(x, y)# ❌ 错误:额外传输出张量
y = torch.empty_like(x)
kernel(x, y) # ValueError: Expected 2 inputs, got 3 with 2 inputs and 1 outputs
# ✅ 正确:只传输入,out_idx 自动创建输出
result = kernel(x)
实践建议:
out_idx,调用时只传输入out_idx,在 prim_func 里把输出也声明为参数,保证"定义多少参数就传多少参数"@tilelang.jit(out_idx=[-1])
def elementwise_add(M, N, block_M, block_N, threads):
@T.prim_func
def main(A: T.Tensor((M, N), "float32"),
B: T.Tensor((M, N), "float32"),
C: T.Tensor((M, N), "float32")):
with T.Kernel(T.ceildiv(N, block_N), T.ceildiv(M, block_M), threads=threads) as (bx, by):
for (local_y, local_x) in T.Parallel(block_M, block_N):
y = by * block_M + local_y
x = bx * block_N + local_x
C[y, x] = A[y, x] + B[y, x]
return main
关键概念:
@tilelang.jit(out_idx=[-1])
def 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.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
关键概念:
T.alloc_shared 缓存频繁访问的数据T.Pipelined 重叠内存加载和计算T.gemm 利用 Tensor Core 加速@tilelang.jit(out_idx=[-1])
def gemv(N, K, BLOCK_N, BLOCK_K):
@T.prim_func
def main(A: T.Tensor((K,), "float16"),
B: T.Tensor((N, K), "float16"),
C: T.Tensor((N,), "float16")):
with T.Kernel(T.ceildiv(N, BLOCK_N)) as bn:
A_shared = T.alloc_shared((BLOCK_K,), "float16")
B_shared = T.alloc_shared((BLOCK_N, BLOCK_K), "float16")
# ✅ 正确:使用 T.Parallel 获取线程索引
for tn in T.Parallel(BLOCK_N):
C_reg = T.alloc_local((1,), "float")
T.clear(C_reg)
for bk in T.serial(T.ceildiv(K, BLOCK_K)):
for tk in T.serial(BLOCK_K):
A_shared[tk] = A[bk * BLOCK_K + tk]
B_shared[tn, tk] = B[bn * BLOCK_N + tn, bk * BLOCK_K + tk]
for tk in T.serial(BLOCK_K):
C_reg[0] += A_shared[tk].astype("float") * B_shared[tn, tk].astype("float")
C[bn * BLOCK_N + tn] = C_reg[0]
return main
关键概念:
T.Parallel() 获取线程索引(推荐方式)T.serial() 用于需要串行执行的操作.astype() 在计算时进行精度转换T.get_thread_binding(),推荐使用 T.Parallel()@T.macro
def Softmax(acc_s, acc_s_cast, scores_max, scores_sum, logsum):
T.copy(scores_max, scores_max_prev)
T.fill(scores_max, -T.infinity("float"))
T.reduce_max(acc_s, scores_max, dim=1, clear=False)
for i in T.Parallel(block_M):
scores_scale[i] = T.exp2(scores_max_prev[i] * scale - scores_max[i] * scale)
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)
T.reduce_sum(acc_s, scores_sum, dim=1)
for i in T.Parallel(block_M):
logsum[i] = logsum[i] * scores_scale[i] + scores_sum[i]
T.copy(acc_s, acc_s_cast)
@tilelang.jit(out_idx=[-1])
def conditional_kernel(N, threads):
@T.prim_func
def main(A: T.Tensor((N,), "float32"),
B: T.Tensor((N,), "float32"),
C: T.Tensor((N,), "float32")):
with T.Kernel(T.ceildiv(N, threads), threads=threads) as bx:
for i in T.Parallel(threads):
idx = bx * threads + i
if idx < N:
C[idx] = T.if_then_else(
A[idx] > 0,
A[idx] + B[idx],
A[idx] - B[idx]
)
return main
@tilelang.jit(out_idx=[-1])
def atomic_reduction(N, K, BLOCK_N, reduce_threads):
@T.prim_func
def main(A: T.Tensor((N, K), "float32"),
C: T.Tensor((N,), "float32")):
with T.Kernel(T.ceildiv(N, BLOCK_N), threads=(BLOCK_N, reduce_threads)) as bn:
C_shared = T.alloc_shared((BLOCK_N,), "float32")
C_accum = T.alloc_local((1,), "float32")
T.clear(C_accum)
for tn in T.Parallel(BLOCK_N):
for k in T.serial(K):
C_accum[0] += A[bn * BLOCK_N + tn, k]
T.atomic_add(C_shared[tn], C_accum[0])
C[bn * BLOCK_N + tn] = C_shared[tn]
return main
T.gemm 内置原语@T.macro 组织代码T.Pipelined 重叠内存操作和计算T.Parallel 优化内存访问T.gemm、T.reduce_sum 等优化原语T.get_thread_binding() 而非 T.Parallel()