Enzyme gradients through parameter-dependent continuous event times are incorrect
I maintainer di solito rispondono entro 2 giorni
@ChrisRackauckas-Claude ci sta già lavorando.
Dal 2/10/2026.
- #570 di @ChrisRackauckas-Claude — aperta
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- julia
- Ambito
- hpc, performance
Direzione di ricerca
Inizia con continuous_event_reproducer.jl e l’entry point continuous_loss, quindi esamina il percorso ContinuousCallback e EnsembleGPUKernel(CPU()) utilizzato dal riproduttore. Eseguilo con il progetto Julia e il branch Enzyme indicati, confronta il risultato dell’evento continuo con il caso riuscito del callback fixed-time e indaga finché le derivate dei parametri non siano tutte -1.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
A continuous callback locates the event correctly in the forward solve, but Enzyme reverse mode returns incorrect event-time sensitivities. For u′=1, u(0)=0, and a reset to zero when u=p, with 0.5<p<1, exactly one event occurs before t=1. Thus u(1)=1-p and every parameter derivative must be -1.
Reproduced on Julia 1.12.7, Enzyme 0.13.201, KernelAbstractions 0.9.42, and SciMLBase 3.53.1, using the CPU backend and the Enzyme restoration branch from https://github.com/SciML/DiffEqGPU.jl/pull/532. This is a remaining limitation of that restoration, not a claim that its changes introduced the event-time problem. The unmodified base cannot execute the ensemble-gradient reproducer because it fails earlier in Enzyme compilation.
using DiffEqGPU, Enzyme, KernelAbstractions, SciMLBase, StaticArrays, Test
function continuous_loss(p)
prob = ODEProblem{false}((u, p, t) -> SVector(1.0), SVector(0.0), (0.0, 1.0), SVector(p[1]))
pf = (prob, ctx) -> remake(prob; p = SVector(p[ctx.sim_id]))
condition(u, t, integrator) = u[1] - integrator.p[1]
affect!(integrator) = (integrator.u = zero(integrator.u))
cb = ContinuousCallback(condition, affect!; save_positions = (false, false))
sol = solve(EnsembleProblem(prob; prob_func = pf, safetycopy = false), GPUTsit5(), EnsembleGPUKernel(CPU(), 0.0); trajectories = length(p), adaptive = false, dt = 0.05, callback = cb, merge_callbacks = true, save_everystep = false)
return sum(s -> sum(s.u[end]), sol.u)
end
p = [0.63, 0.71, 0.84]
@test continuous_loss(p) ≈ 3 - sum(p)
dp = zero(p)
Enzyme.autodiff(Reverse, continuous_loss, Active, Duplicated(p, dp))
@show dp
@test dp ≈ -ones(3) rtol = 1.0e-6
Run with julia +1.12 --project=<environment developed against the Enzyme branch> continuous_event_reproducer.jl.
The forward-value assertion passes. The derivative assertion fails:
dp = [-1.0000000000000027, -0.4999999999999896, -0.7599918704695224]
Test Failed:
Expression: dp ≈ -ones(3) rtol = 1e-6
Evaluated: [-1.0000000000000027, -0.4999999999999896, -0.7599918704695224] ≈ [-1.0, -1.0, -1.0] (rtol=1.0e-6)
The same probe with a fixed-time discrete callback (doubling the exponential solution at t=0.5, using tstops=[0.5] and merge_callbacks=true) passes its analytic gradient check. This distinction should be reflected in documentation: callback execution is supported, but that does not establish correct sensitivities through parameter-dependent event times. Root localization and the differentiated event update need investigation; no cause has been bisected, and GPU behavior has not been verified.
🤖 Investigated with Codex CLI 0.153.4 (model: gpt-6-astra; local session ID: 01a07fcc-1c4f-7ee3-9a1e-51eaab7df293).
- Lingua principale
- Julia
- Stelle
- 331
- Fork
- 43
- Merge medio
- 1g 20h
- PR unite (30g)
- 10
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di SciML/DiffEqGPU.jl
-
Adaptive kernel steppers: t += dt rounding decouples time from integrated length at large tForse già presa @ChrisRackauckas-Claude l’ha presa 42 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
SciML/DiffEqGPU.jl#567 ·
I maintainer di solito rispondono entro 2 giorni
-
Adaptive kernel: ContinuousCallback just before a tstop suppresses the tstop's DiscreteCallbackAperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
SciML/DiffEqGPU.jl#558 ·
I maintainer di solito rispondono entro 2 giorni
-
GPUVern7 Float32 dense output is ~60 ulps off at mid-step for a constant RHS (visible at tstops)Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 62/100
SciML/DiffEqGPU.jl#554 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
SciML/DiffEqGPU.jl#546 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
SciML/DiffEqGPU.jl#540 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di SciML/DiffEqGPU.jl
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
MagneticResonanceImaging/MRIReco.jl#366 ·
I maintainer di solito rispondono entro 3 giorni
-
`AdamW` gives `NaN` for zero-gradient entries of `Float16` parameters (epsilon underflows to 0)Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
FluxML/Optimisers.jl#253 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
JuliaGraphs/GraphNeuralNetworks.jl#736 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 1 giorno