Rust in Everything
基于 burn 0.22.1

常见坑

每一章对着一个报错或一个现象:先用最小的程序把它复现出来(输出是 M2 Max、macOS 27、rustc 1.99.0 上 burn 0.22.1 的原文,GPU 是经 wgpu 的 Metal),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面几部分讲过的,这里只链过去,不再重复。几个坑是上游的问题,章里写明在哪个版本上复现。CUDA、ROCm、Vulkan 上的情况只读了源码,章里另外标出。

  1. type provided when a constant was expected:0.21 的 Tensor<B, 2>、Linear<B>、B: Backend 在 0.22.1 下报 E0747、E0107、E0405;后端从类型参数变成了设备上的值。
  2. 开了 cpu feature,离线构建失败:cpu 一路打开 cubecl-llvm,构建脚本联网下载 LLVM,离线时在 build.rs:66 的 unwrap 上 panic。
  3. No execution backend is enabled:默认 feature 里没有执行后端,Device::default() 运行期 panic,Device::flex() 编译期 E0599。
  4. 关了默认 feature,GPU 变慢:default-features = false 一起关掉 fusion、autotune、autotune 磁盘缓存和 Flex 的 simd、rayon,要补回五个 feature。
  5. The provided tensors are not on the same device:开了 metal 时 Device::default() 是 Auto 的 wgpu 设备,不等于 Device::metal(..)。
  6. input tensor __tensor is on the wrong backend:cat / stack 不查设备;两个 Cube 设备之间要到读数据时才报错。
  7. No Discrete GPU device found:Apple 芯片上 DiscreteGpu(0) 让设备线程 panic,主线程只看到 RecvError。
  8. 同一段代码,Int 在不同设备上位宽不同:Flex 和 Metal 上 Int 是 I32、求和悄悄溢出;Metal 不支持 F64;configure 只能在首次使用前调。
  9. panic 的位置在 burn-tensor 里,不在我的代码里:张量方法没有 #[track_caller],用 RUST_BACKTRACE=1 或 assert_shape!。
  10. 切片越界不报错:slice 先把范围截进形状,越界窗口悄悄变短;要报错就用 narrow。
  11. grad 返回 None:不带原因的 None 背后有九种情形,按判断顺序逐条排除。
  12. graph tape has already been consumed:不支持 retain_graph;detach、每步重算或先合并 loss。
  13. 推理时内存一直涨:autodiff 设备上只做前向,图只增不减,连没有 require_grad 的运算也留记录;推理用 valid() 加普通设备。
  14. the trait bound X: Module is not satisfied:配置和状态字段要标 #[module(skip)];derive(Module) 自带 Clone。
  15. 模型 to_device 之后没有梯度:已初始化的参数变成 to_device 的输出,第一步梯度为 0、第二步 panic;换设备用 fork。
  16. 评估时结果每次不一样:没调 valid(),Dropout 还在 autodiff 设备上随机丢弃。
  17. missing field dropout:#[config(default)] 只给 new 用,旧配置文件读不进新字段。
  18. Record validation error: Missing tensors:字段改名后旧记录对不上路径,用 with_remap_pattern 改名加载。
  19. ShapeMismatch expected [4, 3] found [3, 4]:PyTorch 的 Linear 权重是转置的,要加适配器;方阵会静默读反;Col 布局另有问题。
  20. 同一个种子,顺序不一样:to_device 会 fork 随机数发生器,多 worker 时批的顺序取决于调度。
  21. GPU 上第一次很慢、计时忽快忽慢:不 sync 量到的只是登记;首次含编译和 autotune;缓存跟着当前目录走。
  22. 开了日志,计时和调优结果都变了:CUBECL_DEBUG_LOG 让启动阻塞,autotune 提前收工,选错的结果还写进缓存。
  23. 基准测试测出来几乎为零:没被读的结果一个内核都不启动,几次独立计算又会被合成一个内核。
  24. 出错的 op 不报错,后面读别的张量才报:错误挂在张量上,读到它才交出来,sync 也返回 Ok。
  25. 张量都 drop 了,显存不降:内存池留着页等复用,memory_cleanup 才还回去。
  26. 自定义内核越界读不报错,也不截断:cubecl 0.11.3 的 checked launch 在 MSL / WGSL 上不生效,内核要自己写守卫。

按出在哪里分:

出在哪里坑
升级与 feature1 旧写法、2 cpu feature、3 没有后端、4 默认 feature
设备与 dtype5 默认设备、6 跨设备拼接、7 独立显卡、8 dtype
张量检查9 panic 位置、10 切片截断
自动微分11 grad 为 None、12 两次 backward、13 推理内存
模块与配置14 module(skip)、15 to_device、16 Dropout、17 配置字段
权重与数据18 缺张量、19 PyTorch 形状、20 shuffle 顺序
GPU、融合与 cubecl21 计时、22 日志、23 基准、24 延迟的错误、25 显存、26 越界
flowchart TB
  q{"碰到了什么"}
  q -->|编译或构建失败| bf{"哪一句"}
  bf -->|"E0747 或 E0107"| p1["1 旧写法"]
  bf -->|"Module is not satisfied"| p14["14 module skip"]
  bf -->|"build.rs 下载失败"| p2["2 cpu feature"]
  q -->|运行期 panic| pn{"原文"}
  pn -->|"No execution backend"| p3["3 没有后端"]
  pn -->|"not on the same device"| p56["5 或 6"]
  pn -->|"RecvError"| p7["7 独立显卡"]
  pn -->|"tape already consumed"| p12["12 两次 backward"]
  pn -->|"位置在 burn-tensor"| p9["9 panic 位置"]
  q -->|加载失败| ld{"哪种"}
  ld -->|"missing field"| p17["17 配置字段"]
  ld -->|"Missing tensors"| p18["18 缺张量"]
  ld -->|"ShapeMismatch"| p19["19 PyTorch 形状"]
  q -->|没报错但结果不对| odd{"哪种"}
  odd -->|"梯度是 None 或 0"| p1115["11 或 15"]
  odd -->|"每次结果不同"| p1620["16 或 20"]
  odd -->|"数值溢出或截断"| p810["8 或 10"]
  odd -->|"越界读到怪值"| p26["26 越界"]
  q -->|慢或占内存| perf{"哪种"}
  perf -->|"GPU 变慢"| p4["4 默认 feature"]
  perf -->|"计时不可信"| p2123["21 22 23"]
  perf -->|"内存只涨不降"| p1325["13 或 25"]

💬 关联讨论

发起讨论
加载中...