Rust in Everything
基于 tenferro-runtime 0.8.0

eager

JAX 没有「先算出数、再在张量上调 backward」这种写法:不 jit 的 jax.grad 也是一个函数变换,只是逐个算子执行。tenferro 两种都有。traced 模式是 JAX 式的,见上一部分变换;eager 模式是 PyTorch 式的:variable_from 建叶子,运算在 with_eager_session 里立即执行并记录,loss.backward(&mut engine) 把梯度写进叶子的槽位。这一部分先拿 torch.autograd 对照 eager 的每个接口,再把 eager 和 traced 放在同一个函数、同一个 TRG 上比较结果和时间。eager 的内部机制(trace、残差、梯度槽、缓存)见 tenferro 卷的 eager AD。

  1. backward:variable_from / backward / grad() 对应 requires_grad=True / backward() / .grad,同一个梯度和 PyTorch 逐位相同;不同在边上:第二次 backward 不需要 retain_graph,函数式 grad 的结果总能再求导,在 no_grad 里算的结果调 backward 静默返回空梯度,没有原地运算。
  2. eager 还是 traced:两种模式的梯度逐位相同(JAX 的 jit 和不 jit 反而不同);eager 每次反向约 58 µs 起步,图越深越贵,400 层时是 traced 的 39 倍;整图 eager 的 TRG 4 步就要 7 秒一次,按步分段后 20 步 0.64 s,比分段的 traced 快,因为反向不重算前向。
flowchart TB
  leaf["variable_from"] --> sess["with_eager_session"]
  sess --> run["立即执行"]
  sess --> rec["记 trace 留残差"]
  run --> val["value 可读"]
  rec --> bw["backward"]
  bw --> slot["累加进 grad 槽"]
  bw --> same["同一套语义 VJP"]
  same --> trc["traced grad"]

💬 关联讨论

发起讨论
加载中...