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
{{ message }}
Repository navigation
Value is sometimes not set when using DiffResults #269
Here's an MWE I'm struggling to understand. My best guess sofar is that this is hitting a Julia compiler optimization which somehow eludes the value computation. Unless I'm just holding the thing wrong?
using ReverseDiff: ReverseDiff
using DiffResults: DiffResults
f(x) =sum(abs2, x)
x = [3.0, 5.0]
compiled_tape = ReverseDiff.compile(ReverseDiff.GradientTape(f, x))
functionvalue_and_gradient1!(grad, tape, x)
result = DiffResults.MutableDiffResult(zero(eltype(x)), (grad,))
result = ReverseDiff.gradient!(result, tape, x)
return DiffResults.value(result), DiffResults.gradient(result)
endfunctionvalue_and_gradient2!(grad, tape, x)
result = DiffResults.MutableDiffResult(zero(eltype(x)), (grad,))
result = ReverseDiff.gradient!(result, tape, x)
return DiffResults.value(result), grad
endfunctionvalue_and_gradient_nested1!(grad, tape, x)
y, _ =value_and_gradient1!(grad, tape, x)
return y, grad
endfunctionvalue_and_gradient_nested2!(grad, tape, x)
y, _ =value_and_gradient2!(grad, tape, x)
return y, grad
end
This still reproduces, and it isn't a ReverseDiff bug — it's the Julia optimizer bug JuliaLang/julia#62812, fixed by #57201 in Julia 1.11.5 and never backported to the 1.10 LTS. Wrong on Julia 1.8 – 1.11.4, correct before and after, regardless of the ReverseDiff version. That's why it looked fixed on nightly in February.
Two corrections to the original report: it hits a plain GradientTape too, not just a compiled one, and only the gradient path is affected — jacobian!, hessian! and gradient!(result, f, x) are fine. A package-free reproducer is in the upstream issue.
Fix: no compiler barrier and no version check needed — just re-alias result the way the DiffResults docs ask for (#251), on the whole chain: src/api/gradients.jlandseeded_reverse_pass!(result, ::AbstractTape) in src/api/tape.jl. Still 0 allocations, still type stable.
One note for #261: re-aliasing only helps if every level does it. On 1.10.12, #261 alone is still wrong, tape.jl alone is still wrong, both together are correct. #261 doesn't touch tape.jl, and since that method gets inlined, re-aliasing only in gradients.jl rebinds the same value and changes nothing — so #261 needs one more line to close this.
Activity
nsajko commentedon Feb 16, 2025
This doesn't reproduce on nightly Julia.
nsajko commentedon Feb 16, 2025
BTW, as mentioned on Slack,
--compile=minis a good way to check if a bug is a miscompilation.gdalle commentedon Feb 16, 2025
You're right, with
--compile=minit disappears as well. Not sure what to do about it then.nsajko commentedon Feb 16, 2025
Create a MWE and report an issue to JuliaLang/julia.
Create the MWE by:
Another thing to do is bisect the fix (given that the bug is perhaps fixed on nightly), and see if it's backportable.
gdalle commentedon Feb 16, 2025
Unfortunately I wouldn't even know where to begin to inline ReverseDiff. I tried removing it entirely and the effect disappeared.
devmotion commentedon Sep 16, 2026
This still reproduces, and it isn't a ReverseDiff bug — it's the Julia optimizer bug JuliaLang/julia#62812, fixed by #57201 in Julia 1.11.5 and never backported to the 1.10 LTS. Wrong on Julia 1.8 – 1.11.4, correct before and after, regardless of the ReverseDiff version. That's why it looked fixed on nightly in February.
Two corrections to the original report: it hits a plain
GradientTapetoo, not just a compiled one, and only the gradient path is affected —jacobian!,hessian!andgradient!(result, f, x)are fine. A package-free reproducer is in the upstream issue.Fix: no compiler barrier and no version check needed — just re-alias
resultthe way the DiffResults docs ask for (#251), on the whole chain:src/api/gradients.jlandseeded_reverse_pass!(result, ::AbstractTape)insrc/api/tape.jl. Still 0 allocations, still type stable.One note for #261: re-aliasing only helps if every level does it. On 1.10.12, #261 alone is still wrong,
tape.jlalone is still wrong, both together are correct. #261 doesn't touchtape.jl, and since that method gets inlined, re-aliasing only ingradients.jlrebinds the same value and changes nothing — so #261 needs one more line to close this.Realias `result` on the gradient path (fixes #269)