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