源码地图
主线位置:三条主线经过的代码分布在哪些 crate 里。算子主线从
burn-tensor出发,经burn-dispatch分到burn-autodiff、burn-fusion,落到burn-flex或burn-cubecl,再下到 cubecl 和 cubek;求导主线几乎全在burn-autodiff里;训练主线在burn-core、burn-nn、burn-optim、burn-train里,只在算张量时进入算子主线。
flowchart TB app["应用 crate"] --> burn["burn 再导出"] burn --> core["burn-core 模块 记录 数据"] burn --> nn["burn-nn / optim / train / store"] nn --> core core --> tensor["burn-tensor 张量 API"] tensor --> dispatch["burn-dispatch 全局后端"] dispatch --> ad["burn-autodiff 装饰器"] dispatch --> flex["burn-flex CPU"] dispatch --> cubeb["burn-cubecl GPU"] cubeb --> fusion["burn-fusion 装饰器"] cubeb --> cfus["burn-cubecl-fusion"] cubeb --> cubek["cubek 内核库"] cubek --> cubecl["cubecl 语言与运行时"] ad --> backend["burn-backend 后端接口"] flex --> backend fusion --> ir["burn-ir"] backend --> std["burn-std"]
行数是 git show <tag>:<path> | wc -l 数的 .rs 文件行数(含注释和空行,不含 tests/ 目录,但含 src/ 里的 tests.rs),只用来比较各块的大小。burn 工作区按 Cargo.toml 的 members = ["crates/*", ...] 有 38 个 crate,另有 examples 和 xtask;下面按层分组。
用户 API:burn、burn-core、burn-tensor 和上面几层
| crate | 行数 | 入口 | 做什么 | 讲它的页 |
|---|---|---|---|---|
burn | 328 | src/lib.rs | 只做再导出:pub use burn_core::*,再按 feature 挂上 nn、optim、train、store、vision 等模块;crate 文档里有完整的 feature 列表 | 怎么读这一卷 |
burn-tensor | 21 957 | src/tensor/api/base.rs(3 927 行)、bridge/、device.rs(1 675 行) | Tensor<D, K> 和全部张量方法、Device 门面、把调用转进 Dispatch 的 BridgeTensor | 02 张量 |
burn-core | 9 147 | src/module/base.rs 的 Module trait、module/param/、config.rs、store/、data/ | 模块、参数、Config、记录、数据加载器;后端 crate 和 Device 构造函数的 feature 也在这里汇总 | Module 派生、Config |
burn-derive | 3 199 | src/lib.rs 的 module_derive、config | #[derive(Module)]、#[derive(Config)] 等过程宏 | Module 派生 |
burn-nn | 25 840 | src/modules/、loss/ | Linear、卷积、归一化、注意力等层,各种损失函数 | nn 模块 |
burn-optim | 9 929 | src/optim/base.rs 的 Optimizer、module/module_optimizer.rs、grads.rs | 优化器(Adam、SGD、Muon 等)、GradientsParams、学习率调度 | 优化器 |
burn-train | 30 237 | src/learner/ | Learner 主循环、指标、事件、checkpoint、TUI | Learner 与数据 |
burn-store、burn-pack、pytorch-reader | 10 001、2 461、6 150 | burn-store/src/、burn-pack/src/lib.rs、pytorch-reader/src/lib.rs | 模型存取:burnpack 二进制格式、safetensors、PyTorch .pt 读入(pytorch-reader 不依赖 PyTorch 也不依赖 burn) | 存储与加载 |
burn-dataset | 7 989 | src/ | 数据集与变换(下载器要联网,本卷不用) | Learner 与数据 |
burn-einsum | 1 113 | src/lib.rs | einsum! 的方程解析,和后端无关 | 检查与报错 |
burn-train 无条件依赖 burn-flex(burn-flex = { workspace = true, features = ["default"] }),但在 tag 下 git grep burn_flex crates/burn-train 找不到任何引用:开了 train 就会编译 Flex,不管用不用它。
分派:burn-dispatch 和 burn-backend-extension
| crate | 行数 | 入口 | 做什么 | 讲它的页 |
|---|---|---|---|---|
burn-dispatch | 6 528 | build.rs、src/backend.rs(1 192 行)的 Dispatch、device.rs、tensor.rs、ops/ | 唯一的全局后端:DispatchDevice / DispatchTensor 每个后端一个变体,每个 op 按设备 match;跨后端搬运 | Dispatch |
burn-backend-extension | 4 246 | src/catalog.rs 的 BACKENDS、dispatch.rs | 过程宏 crate:#[backend_dispatch] 为 Dispatch 的每个 op 生成 match;#[backend_extension] 让下游 crate(burn-linalg、burn-vision 等)加自己的 op | Dispatch |
burn-dispatch 是整个依赖图的腰:上面的 crate 只认识 Dispatch 这一个后端,下面每个后端 crate 都是它的可选依赖。0.21 里它已经存在(#4508,首次发布于 v0.21.0-pre.2),那时 Tensor 还带后端类型参数,Dispatch 只是可选的一种后端;metal、vulkan、webgpu 三个 wgpu 后端在它里面互斥,同时打开时构建脚本打印「Only one WGPU backend can be enabled at once」并把三个都关掉。0.22 里七种 cubecl 运行时合成一个 Cube 变体,见怎么读这一卷的「burn-dispatch 的三个 cfg」。
后端接口:burn-backend、burn-std、burn-ir
| crate | 行数 | 入口 | 做什么 | 讲它的页 |
|---|---|---|---|---|
burn-backend | 13 429 | src/backend/base.rs 的 BackendTypes、Backend;backend/ops/tensor.rs(1 964 行)等 | 后端要实现的全部 trait:FloatTensorOps、IntTensorOps、ModuleOps……;很多 op 有用别的 op 拼出来的默认实现 | Backend trait |
burn-std | 9 442 | src/ | 和后端无关的公共类型:TensorData、DType、Shape、Bytes、运行期配置 | Tensor 与 Kind |
burn-ir | 8 311 | src/operation.rs 的 OperationIr、tensor.rs 的 TensorIr | 每个 op 的可序列化描述;Fusion、Router、Remote、Capture 都靠它 | burn-ir |
装饰器:包在别的后端外面
| crate | 行数 | 入口 | 做什么 | 讲它的页 |
|---|---|---|---|---|
burn-autodiff | 11 378 | src/backend.rs 的 Autodiff<B, C>、ops/tensor.rs(4 830 行)、runtime/、grads.rs | 套在任何后端外面记录计算图、做反向传播 | 04 自动微分 |
burn-fusion | 25 173 | src/backend.rs 的 Fusion<B>、client.rs、server.rs、stream/、search/ | 不立刻执行,把 op 记成 burn-ir 送进流,攒够了再决定怎么融合 | Fusion 装饰器、融合搜索 |
burn-router | 9 152 | src/backend.rs 的 BackendRouter<R> | 把 op 记成 IR,经一个 RouterChannel 送到别处执行;burn-remote 和 burn-capture 的底座 | 一句带过 |
burn-remote、burn-communication | 9 132、1 136 | burn-remote/src/lib.rs | 远程设备:客户端发 op、服务端在自己的设备上跑(默认 Iroh 传输,另有 WebSocket,服务端用 axum) | 一句带过 |
burn-capture | 1 191 | src/lib.rs | 只记录不执行的「后端」,用于导出计算图 | 一句带过 |
Autodiff<B, C> 和 Fusion<B> 是真正的类型层装饰器:类型参数就是被包的后端,Backend::name 也一层套一层(autodiff<fusion<cubecl<...>>>)。BackendRouter<R> 的参数是一个通道而不是后端,它不包某个后端,而是把 op 送给通道另一头的解释器。
实现:burn-flex、burn-cubecl 和下面的 cubecl、cubek
| crate | 行数 | 入口 | 做什么 | 讲它的页 |
|---|---|---|---|---|
burn-flex | 37 033 | src/backend.rs 的 Flex、ops/(conv.rs 3 056 行、reduce.rs 2 860 行)、ops/matmul.rs | 纯 Rust 的 eager CPU 后端,matmul 交给 gemm 0.19,SIMD 用 macerator,并行用 rayon;支持 no_std 和 wasm | Flex:CPU 后端 |
burn-cubecl | 20 684 | src/backend.rs 的 CubeBackend、lib.rs 的 Cube、ops/、kernel/ | 所有 cubecl 运行时共用的一个后端;开 fusion 时 Cube = Fusion<CubeBackend>;matmul、reduce、卷积交给 cubek | burn-cubecl 后端 |
burn-cubecl-fusion | 16 660 | src/engine/、optim/ | burn-fusion 决定哪些 op 一组,它为这一组生成并启动融合内核 | 生成融合内核 |
burn-wgpu、burn-cuda、burn-rocm、burn-cpu | 253、58、26、61 | src/lib.rs | 只是门面:给 burn-cubecl 打开某个 cubecl 运行时的 feature | wgpu 与 Metal |
burn-ndarray、burn-tch | 13 015、4 434 | src/lib.rs 顶部的 #![deprecated] | 弃用:ndarray 0.17 的 CPU 后端、LibTorch(tch 0.22)绑定 | Flex:CPU 后端 |
cubecl 和 cubek 是两个单独的仓库。在 Metal 这条路上用到的部分(cubecl 0.11.3、cubek 0.3.1):
| crate | 行数 | 做什么 | 讲它的页 |
|---|---|---|---|
cubecl-macros、cubecl-core | 11 170、40 475 | #[cube] 宏把 Rust 函数体展开成「构造 IR 的代码」;前端类型(缓冲区参数 &[T] / &Tensor<T>、向量化的 Vector<F, N>、comptime) | #[cube] 内核 |
cubecl-ir、cubecl-opt | 18 351、8 800 | 内核 IR 和优化 pass | #[cube] 内核 |
cubecl-runtime、cubecl-server | 16 845、15 506 | Client、内核提交、autotune(tune/);内存池、流、编译管线 | 运行时与 Client、autotune |
cubecl-wgpu、cubecl-cpp | 11 252、10 804 | wgpu 运行时;cubecl-cpp 的 metal 方言把 IR 编成 MSL(cubecl 的 metal = ["wgpu-msl"]) | wgpu 与 Metal |
cubecl-environment、cubecl-common | 11 150、9 194 | 跨 std / no_std / wasm 的同步原语、block_on、配置、持久缓存(turso 数据库);设备服务线程 | 运行时与 Client |
cubecl-std | 11 480 | cube 标准库,含测设备吞吐的内核(autotune 的上界从这里来) | autotune |
cubek-matmul、cubek-tile | 37 106、32 252 | matmul 内核族和它们共用的 tile 抽象 | burn-cubecl 后端 |
cubek-reduce、cubek-attention、cubek-convolution 等 | 9 924、8 876、8 208 … | 归约、注意力、卷积、池化、随机数、量化 | 一句带过 |
cubecl 还有 cubecl-cuda(4 274)、cubecl-hip(3 020)、cubecl-cpu(3 335)+ cubecl-llvm(13 449)、cubecl-spirv(4 890)、原生的 cubecl-metal(2 545)这些运行时和编译器,本卷只读源码;burn 的 metal feature 用不到 cubecl-metal。
领域扩展
burn-vision(9 350)、burn-linalg(2 991)、burn-signal(1 741)、burn-rl(1 235)是同名 feature 打开的领域算子和强化学习工具,本卷一句带过。burn-nn 依赖 burn-linalg,所以后者总会被编译。测试用的 burn-backend-tests(6 242)、burn-no-std-tests(460)不讲。
依赖树有多大
同一个空 main、不同 feature,用 cargo tree -e normal 数去重后的包(锁文件相同):
features = ["flex"] 157 个包,其中 cubecl/cubek 3 个
features = ["metal"] 368 个包,其中 cubecl/cubek 26 个
features = ["flex", "metal"] 396 个包,其中 cubecl/cubek 26 个
default-features = false, features = ["flex"] 112 个包
问: 只开 flex,为什么依赖树里还有 cubecl?
答: 那 3 个是 cubecl-common、cubecl-environment、cubecl-zspace,来自 burn-std 的直接依赖,不是 GPU 运行时:burn-std 用它们提供跨 std / no_std / wasm 的同步原语、block_on、流 id 和配置。cubecl-core、cubecl-runtime、cubek 只在打开某个 cubecl 运行时 feature 时才进来。代价是即便只用 CPU,TensorData、Shape 这些基础类型也和 cubecl 的版本绑在一起(burn 0.22.1 的工作区写的是 cubecl-common = "0.11.1")。
小结
- 五层:用户 API(
burn只再导出,burn-tensor是张量 API,burn-core是模块和记录)→ 分派(burn-dispatch,整个图的腰)→ 后端接口(burn-backend、burn-std、burn-ir)→ 装饰器(burn-autodiff、burn-fusion,以及基于 IR 转发的burn-router/burn-remote/burn-capture)→ 实现(burn-flex、burn-cubecl加 cubecl、cubek)。 - 最大的几个 crate:cubecl-core 4.0 万行、burn-flex 3.7 万、cubek-matmul 3.7 万、burn-train 3.0 万、burn-nn 2.6 万、burn-fusion 2.5 万。
burn-wgpu这些「后端 crate」在 0.22 只剩几十到两百多行,真正的后端是burn-cubecl一个,运行时由设备值决定。- 只开
flex拉进 157 个包,开metal是 368 个;burn-train不管用不用都会编译burn-flex。