You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix type-inference failure for nested submodels (#1427)
Evaluating a submodel used to recurse through the shared
`_evaluate!!(::Model, ::AbstractVarInfo)` method. Each submodel level
constructs a contextualized `Model{..., Ctx}` whose `Ctx` parameter
gains another context layer. In nested submodels, Julia's recursion
limiter (`limit_type_size`) sees the same `_evaluate!!(::Model, ...)`
method recurring with a more complex `Model{..., Ctx}` call signature,
widens the `Model` argument to abstract `Model`, and inference can no
longer resolve `model.f` precisely. The model return type then collapses
to `Any`, evaluation falls back to runtime dispatch, and primal/gradient
evaluation slows down.
Submodel evaluation now calls the generated model function directly
instead of going through `_evaluate!!(::Model, ...)`. This removes the
recursive `_evaluate!!(::Model, ...)` call edge while leaving the
recursive `_evaluate!!(::Submodel, ...)` edge intact; the remaining
submodel edge is not widened by the limiter. As a result, inference
stays type stable for nested submodels.
Adds type-stability (`@inferred`) and allocation (`iszero(allocs)`)
regression tests at both the evaluation and `LogDensityFunction` levels,
covering several nesting depths under `UnlinkAll`/`LinkAll`. The tests
were verified to fail on the unfixed code. Also bumps the version to
0.42.1 and adds a HISTORY.md entry.
See TuringLang/Turing.jl#2844
Above is written by Claude/Codex, lightly touched by me.
Copy file name to clipboardExpand all lines: HISTORY.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,9 @@
1
+
# 0.42.1
2
+
3
+
Fixed a type-inference failure that made nested submodels (a `~ to_submodel(...)` statement inside a model that is itself evaluated as a submodel) very slow.
4
+
5
+
Previously, evaluating a submodel recursed through the shared `_evaluate!!(::Model, ::AbstractVarInfo)` method. Each level of nesting adds another context layer to the `Model` type, which tripped Julia's type-inference recursion limit: from the first level of nesting onwards the return type was inferred as `Any` and evaluation fell back to runtime dispatch, slowing down both primal and gradient evaluation (the primal slowdown was roughly 15x, growing with nesting depth). Submodel evaluation now calls the model function directly, keeping nested submodels type-stable. See [Turing.jl#2844](https://github.com/TuringLang/Turing.jl/issues/2844).
6
+
1
7
# 0.42.0
2
8
3
9
`LogDensityFunction` now performs AD preparation through AbstractPPL's `prepare` / `value_and_gradient!!` interface instead of calling DifferentiationInterface directly. Internally this removes the `_use_closure` heuristic and the explicit `DI.Constant` plumbing; the choice between closure and constants now lives in AbstractPPL.
0 commit comments