Rust in Everything
基于 tenferro-runtime 0.8.0

常见坑

每一章对着一个报错或一个现象:先用最小的程序把它复现出来(输出是 M2 Max、macOS 27、rustc 1.99.0 上 tenferro-rs 0.8.0 的原文,CPU 默认用 native provider),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面几部分讲过的,这里只链过去。有几个坑是上游的问题(einsum 的广播梯度会悄悄算错、三个输入的广播前向失败、SVD 梯度的 NaN),章里写明在 0.8.0 上复现。CUDA 本机跑不了,只有「没有驱动时 panic」这一条是实测的。

0.7.1 版的二十六个坑里,有八个在 0.8.0 已经不存在或换了样子:会话没了,prelude-session、全局仲裁器串行和「每次新建后端」跟着消失(后者换成第 7 条);WebGPU 删了,它的 feature 陷阱换成第 3 条的 CUDA 版,WebGPU 不支持的运算和 Apple 例子编不过两条一起删掉;5 个输入的融合区域不再规划;默认 einsum 规划改成确定的贪心,结果末位不再随进程变。

  1. 矩阵乘结果不对,也没有报错:行主序数据交给 from_vec_col_major,只检查元素个数;改用 from_vec_row_major。
  2. native and blas are mutually exclusive:只在 tenferro-cpu 上开 blas-accelerate,9 个错误里真正的原因排第三。
  3. EagerExtensionBackendKind::Cuda not covered:开了 autodiff 的运算族 crate 要一起开 cuda。
  4. this build selects no CPU numerical backend:关了默认 feature 又没选 BLAS,能编译,matmul 运行时才报 Unsupported。
  5. type annotations needed(assert_eq 一个空形状):用到 einsum 时 omeco 带进 serde_json,&[] 推断不出来。
  6. dot_general: dtype mismatch: expected F64, actual F32:直接运算不提升 dtype,eager 和 traced 会。
  7. 每次调用都新建 engine:小运算慢几倍,自定义参数的线程池不进缓存。
  8. 12 个线程比 8 个慢:默认宽度算上了能效核;运算后 team 成员还在自旋。
  9. cannot add &TracedTensor to Result:traced 运算返回 Result,链式写法要逐个 ?。
  10. einsum notation must contain exactly one '->':箭头必须有,括号写法只有 traced 的 NestedEinsum 接受。
  11. EinsumOptimize::False 反而慢几百倍:不是从左到右,从第四个输入起两两配对,造出外积。
  12. einsum 的梯度形状不对:长度 1 的广播在反向里没被求和,上游 bug。
  13. label 106 has extents 1 and 3:三个输入时整条收缩交给 cpueinsum,跳过了广播,上游回归。
  14. cannot map label occurrences [105, 105] into [105]:i->ii 可以,i,i->ii 不行。
  15. the trait From<tenferro_einsum::Error> is not implemented:eager 会话闭包里的 ?,迁移指南的改法也编不过。
  16. ContractionScalar::one: dtype mismatch: expected I64, actual F32:整数收缩不支持,报错把期望和实际写反。
  17. unsupported vjp AD rule for tenferro-linalg.linalg.v1:默认规则集是空的,要 AdContext 加各族的 semantic_ad_rules()。
  18. 第二次 backward 后梯度翻倍:eager 梯度累加,要 clear_grad;对中间结果求导报 grad is inactive。
  19. no engine "tenferro-cpu.default.v1" is registered:没注册引擎描述、没装运算族模块;后者在 prepare 报,却标成 Runtime::run。
  20. has no runtime input binding:编译期错误;输入规格多一个也报错;输入顺序按图走。
  21. add: incompatible shapes: lhs=[3], rhs=[4]:符号形状的错误推迟到 run;同一个 slice 错误分三个阶段报。
  22. prepared specialization projection mismatch:Prepared 按准备时的具体维度特化,换形状要重新 prepare。
  23. SVD 的梯度全是 NaN:非方阵里恰好为 0 的奇异值,derivative_eps 也救不了,上游 bug。
  24. 280 MiB 的矩阵做 SVD 用了 1.5 GiB:薄 SVD 总是给出完整的 U、S、Vt,还有残差校验的缓冲;只要前几个向量就用 Gram 加 eigh。
  25. reshape element-count mismatch: from 6 to 12:dynamic_truncate 在 2 维以上求导失败,上游 bug。
  26. unsupported vjp AD rule for tenferro-fft.rfft.v1:实数 FFT 没有反向规则,先转复数。
  27. det_read: incompatible shapes: lhs=[2], rhs=[3]:0.8.0 起非方阵直接拒绝,0.7.1 会返回一个错值。
  28. missing shape hint for traced tensor:sigmoid、softmax、layer_norm 这些组合运算不收符号形状的输入。
  29. 越界下标不报错,取到边上的值:take_along_axis 按 StableHLO 的语义夹到范围内,和 NumPy 不同。
  30. Unable to dynamically load the "cuda" shared library:没有驱动时 cuda_devices() panic,先 gpu_available(),上游 bug。
  31. view is not slice-contiguous:转置视图不能 as_slice / reshape_view,先 to_contiguous;动态张量没有 Clone。

按出在哪里分:

出在哪里坑
数据与张量1 列主序、6 dtype、31 视图
crate 与 feature2 native 与 blas、3 cuda feature、4 没有 provider、5 推断
engine 与线程7 每次新建、8 线程宽度
traced 与运行时9 Result 链、19 引擎、20 占位符、21 推迟的形状错误、22 换形状、28 组合运算
einsum10 方言、11 False、12 广播梯度、13 广播前向、14 重复下标、15 会话里的 ?、16 整数
自动微分17 运算族规则、18 累加、23 SVD、25 截断、26 rfft
线性代数与索引24 SVD 内存、27 非方阵、29 越界下标
GPU30 CUDA 驱动
flowchart TB
  q{"碰到了什么"}
  q -->|编译失败| cf{"哪一句"}
  cf -->|"mutually exclusive"| p2["2 native 与 blas"]
  cf -->|"non-exhaustive"| p3["3 cuda feature"]
  cf -->|"type annotations"| p5["5 推断"]
  cf -->|"cannot add"| p9["9 Result 链"]
  cf -->|"From 没实现"| p15["15 会话里的 ?"]
  q -->|运行时报错| rt{"出在哪"}
  rt -->|"einsum"| e["10 13 14 16"]
  rt -->|"prepare 或 run"| r["19 20 21 22 28"]
  rt -->|"求导"| a["17 25 26"]
  rt -->|"其他"| o["4 6 27 31"]
  q -->|结果不对| w{"哪里不对"}
  w -->|"数值错位"| p1["1 列主序"]
  w -->|"梯度"| g["12 18 23"]
  w -->|"越界没报错"| p29["29 下标"]
  q -->|慢或占内存| s["7 8 11 24"]
  q -->|panic| p30["30 CUDA 驱动"]

💬 关联讨论

发起讨论
加载中...