9 月 30 日上午,DeepSeek 干了一件比发模型更有嚼头的事:把面向华为昇腾平台的一整套底层基础设施开源了。消息里最扎眼的是一个词------TileLang。很多人把它理解成「DeepSeek 用的那门算子语言」,也有人拿它对标 CUDA。
不夸张地说,这可能是 2026 年国产算力生态里最值得动手试一试的东西。因为它解决的是一个很具体、很痛的工程问题:想给 NPU/GPU 写高性能算子,以前只能硬啃 CUDA 或 Ascend C,门槛高得离谱;而 TileLang 用类 Python 的语法,让这件事降到了「会写 Python 就能上手」。
这篇文章不聊投资、不聊股价,就带你从零把 TileLang 跑起来,写完一个真正能跑的矩阵乘法(GEMM)算子。
DeepSeek 这次到底开源了什么
先把这次开源的范围说清楚,不然容易把 TileLang 当成全部。DeepSeek 开的是一层层铺好的软件栈,和它此前在英伟达平台上开源的组件一一对应,一共六件套:
| 组件 | 干什么 | 对应英伟达侧 |
|---|---|---|
| TileLang | 高级语言编译工具,写算子 | 编译工具链 |
| DeepGEMM | 矩阵运算库 | GEMM 算子库 |
| DeepEP | 跨设备通信库 | 集合通信 |
| TileKernels | 向量计算与访存算子 | 基础算子 |
| FlashMLA | 稀疏注意力 | 注意力加速 |
| DeepSelect | 数据筛选 | 数据层工具 |
把这六件套按层次看,结构就清楚了:应用层是 TileLang(封装了昇腾原生的 Ascend C,用高级语言写算子还不掉性能);核心层是 DeepGEMM、DeepEP、TileKernels、FlashMLA、DeepSelect 这几个高性能库;再往下就是和华为一起优化的昇腾 950、128 卡超节点。
一句话概括这次开源的价值:以前国产硬件最缺的不是芯片,是能把芯片性能榨出来的那套软件栈。 DeepSeek 把自己在英伟达上已经验证过的一套东西,原样搬到了昇腾上,等于把中间这块最难啃的骨头先啃了。
为什么 DeepSeek 要花大力气啃这块骨头?背景很硬。据多家媒体报道,DeepSeek 已经下了超过 25 亿美元的订单,采购至少 16 万颗华为昇腾 950DT 加速器,准备部署到内蒙古乌兰察布在建的数据中心。梁文锋在投资人的闭门会上,把「用华为或其他国产芯片训练模型」说成公司当前最大的一笔赌注,明言这件事必须成。
赌注背后是个很现实的账:AI 训练的代码,最早全是冲着英伟达 Tensor Core、WGMMA 指令写的。要搬到昇腾上,得把每一处 cuBLAS、NCCL 调用换掉,约等于把整套软件栈重写一遍。TileLang 这条「高级语言中间件」路线,目标就是让这种重写以后只发生一次------写完一套算子,剩下的适配交给编译后端去对不同芯片各做各的事。
TileLang 是什么,和 CUDA、Triton 差在哪
TileLang 是一个领域专用语言(DSL),专门用来写高性能的 AI 算子。它有几个关键设计:
先看语法:类 Python,不是 C++。 开发者写的是 Python 风格的代码,通过 @T.prim_func 定义 kernel,用 T.Kernel、T.copy、T.gemm 这些原语描述数据流,编译器和后端负责把它翻译成目标硬件的指令。
再看出处:它不是从零造编译器,而是站在 Apache TVM 之上。 TileLang 复用了 TVM(陈天奇团队那个开源机器学习编译器)现成的编译能力,在上面包装了一层专门针对「分块计算」的语法。这也是它能同时支持多家后端的原因------换一块芯片,改编译目标就行,算子逻辑基本不用动。
再看路线:它走的是「硬件可感知」,和 Triton 相反。 Triton 的设计哲学是「硬件不可知」,尽量屏蔽硬件细节,通用但容易够不到专用硬件的底层红利;TileLang 反过来,允许你用 T.alloc_shared 这类注解把内存层级、张量化、流水线这些信息喂给编译器,让编译器在「懂硬件」的前提下做调度。这也是为什么它在昇腾这种 Cube/Vector 分离架构上能拿到近硬件上限的性能。
出场背景也值得一提:TileLang 最早由北京大学团队在 TVM 上孵化,DeepSeek 拿去推到生产、验证之后又反向捐赠回开源社区。截至 2026 年 9 月,仓库已经有 7.6k star。它给开发者提供了三层接口:完全硬件无关的高层接口、针对不同架构优化过的算子库,以及让专家直接操作线程同步、内存合并的底层原语。
完整的解决方案就在后半部分,包含可直接复用的代码模板【关注后可见】
环境准备
TileLang 的安装不重。前提是要有一个 Python 3 环境,装好对应的 PyTorch:
bash
# 有 CUDA 的机器,先装带 CUDA 的 PyTorch,再装 tilelang
pip install torch
pip install tilelang
在纯 CPU 的机器上也能跑通(kernel 会被编译到 CPU 后端,只是没 GPU 那么快),用来验证语法和逻辑完全够用。AMD 的卡则先装 ROCm 版的 PyTorch,再装 tilelang,同样的 wheel 直接就能用。
装完验证一下:
python
import tilelang
print(tilelang.__version__)
5 步写出一个 GEMM 算子
矩阵乘法是几乎所有 AI 算子的地基,学会了它,别的算子思路就通了。下面这个例子是标准的 tile 化 GEMM:把大矩阵切成小块,A、B 切块后搬到共享内存里做矩阵乘,结果累加到寄存器碎片上,最后写回。
python
import torch
import tilelang
import tilelang.language as T
def matmul(M, N, K, block_M, block_N, block_K,
dtype="float16", accum_dtype="float"):
@tilelang.jit(out_idx=[-1])
def kernel(block_M=block_M, block_N=block_N, block_K=block_K,
dtype=dtype, accum_dtype=accum_dtype):
@T.prim_func
def main(
A: T.Tensor((M, K), dtype),
B: T.Tensor((K, N), dtype),
C: T.Tensor((M, N), dtype),
):
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), dtype)
B_shared = T.alloc_shared((block_K, block_N), dtype)
C_local = T.alloc_fragment((block_M, block_N), accum_dtype)
T.clear(C_local)
for k in T.Pipelined(T.ceildiv(K, block_K), num_stages=3):
T.copy(A[by * block_M, k * block_K], A_shared)
T.copy(B[k * 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
return kernel
if __name__ == "__main__":
M = N = K = 1024
block_M = block_N = block_K = 128
a = torch.randn(M, K, device="cuda", dtype=torch.float16)
b = torch.randn(K, N, device="cuda", dtype=torch.float16)
c = matmul(M, N, K, block_M, block_N, block_K)(a, b)
torch.testing.assert_close(c, a @ b, rtol=1e-2, atol=1e-2)
print("GEMM kernel 与 PyTorch 结果一致")
看懂这五步,TileLang 的骨架你就摸清了:
T.prim_func声明 kernel:入参就是三个张量,TileLang 会据此推导内存布局和数据流。T.Kernel定义并行的 tile 网格 :bx、by是 tile 的坐标,在 CUDA 上对应 blockIdx,在 CPU 上就是外层循环,一套代码两种后端。T.alloc_shared和T.alloc_fragment显式分层:共享内存放 A、B 的切块,寄存器碎片放累加结果,这是性能的关键------数据在内存层级之间怎么流,由你说了算。T.Pipelined+T.copy做流水线搬运 :num_stages控制重叠的层数,让搬运和计算重叠起来,掩盖访存延迟。T.gemm做矩阵乘核心:编译器把它映射到底层硬件指令,剩下的调度交给后端。
跑通之后,可以顺手做两个实验:把 num_stages 从 3 调成 2 或 4 看性能变化。进阶一步,融合 ReLU 只需在 T.gemm 循环之后、T.copy 写回之前加一段:
python
for i, j in T.Parallel(block_M, block_N):
C_local[i, j] = T.max(C_local[i, j], 0)
这样就等于把激活函数和矩阵乘融进同一次寄存器操作,省掉一次从全局内存把整个输出矩阵读出来、再写回去的往返。在长序列推理里,这种「少一次访存」的做法往往就是几倍的吞吐差,也是 TileLang 这类算子语言真正值钱的地方------它让你能亲手把这次往返省掉。
昇腾版:同一套语言,两套后端
回到这次开源的重点。昇腾版的 TileLang 做的事很直接:把底层 Ascend C 指令封装起来,让开发者不用手写 Cube/Vector 的同步和内存搬运。
具体来说,昇腾 NPU 是 Cube(矩阵)核和 Vector(向量)核分离的架构,手写 Ascend C 要自己管 SetFlag/WaitFlag 同步、自己切块、自己搬 L1/L0 内存,最痛。TileLang 昇腾版在编译期自动识别 T.gemm 归 Cube 核、T.exp 这种归 Vector 核,自动插入同步、自动做双缓冲流水,开发者这层全免了。
这也是最值得记住的一句话:同一套算子代码,切到 CUDA 后端就能上英伟达,切到昇腾后端就能上华为,T.Kernel、T.Parallel 这些抽象不变,只有编译目标在变。 对有国产算力迁移需求(或者干脆有「哪天英伟达断供」预期)的团队来说,这层中间件的价值比单一某个模型大得多。
至于性能,DeepSeek 披露了几个可以复现的数字:DeepGEMM 昇腾版在部分 Dense GEMM 测试里做到了硬件理论值的 99.8%;用 TileLang 写的 DeepSeek V3.2 稀疏注意力 TopK 算子,比原生 PyTorch 实现快 2 到 20 倍;一个原本要 500 多个代码块的高性能 FlashMLA 实现,被压成了 50 行 TileLang,还保留了 95% 的性能。
上手前你大概率会问的三个问题
没有昇腾卡,学这个还有用吗? 有用,而且现在正是学的时候。TileLang 的主仓库本身就能在 CUDA 和 CPU 上跑,昇腾版只是新增的一类后端。你完全可以在自己的显卡上把语法、tile 切分、流水线这些核心概念吃透,等国产算力真到手里的那天,切换成本基本为零。
它会把 CUDA、Triton 都替代掉吗? 短期内不会。CUDA 的生态厚度、Triton 的通用性都还在,TileLang 目前最鲜明的战场是「需要榨出专用硬件上限」的场景,尤其是昇腾这种 Cube/Vector 分离的架构。把它理解成国产算力这条路上一个更顺手的工具,而不是要你立刻抛弃手上的东西。
普通业务开发者需要懂这个吗? 大部分人不需要天天写算子。但如果你在做模型部署、推理加速、国产化适配,或者只是想搞明白「为什么这套代码能跑得这么快」,TileLang 是一条很短的学习路径,一个周末足够从零写到能跑的 GEMM。
写给你的三条建议
如果你正打算上手,有三条很实际的经验:
- 先跑 CPU,再上真硬件。 昇腾 NPU 不是人人都有,但 TileLang 的语法和逻辑在 CPU/CUDA 上就能先练熟,等真需要迁移时再切昇腾后端,学习成本几乎为零。
- 把性能优化的重心放在数据流,而不是调参。 TileLang 的哲学是「调度空间与数据流解耦」,先想清楚数据在全局内存、共享内存、寄存器之间怎么流,再谈
num_stages、tile 大小这些参数。 - 国产算力这波,工具链比模型更值得跟。 模型会过时,但一套能把硬件性能榨出来的编译工具链会沉淀下来。TileLang 是当前事实上的国产 DSL 标杆,值得花一个周末。
延伸阅读:
看完有收获?点个关注 👆 我会持续分享更多AI编程实战教程。