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
Reduce per-step allocations in MIRK loss functions
Three key changes to reduce allocations in the hot path (loss function
and Jacobian evaluation called every Newton iteration):
1. Remove Logging.with_logger(NullLogger()) wrapper from get_tmp
- The wrapper allocated a closure + task-local context on EVERY call
- get_tmp is called 50+ times per loss evaluation
- The warning it suppressed only occurs during adaptive cache resize
- This single change reduced total solve allocations by ~60%
2. Eliminate array comprehensions in MIRK loss functions
- Replaced `[get_tmp(r, u) for r in residual]` with direct DiffCache
passing to Φ! and recursive_flatten!
- Added _maybe_get_tmp helper for Φ! to handle both DiffCache and
plain array residuals
- Added recursive_flatten!/recursive_flatten_twopoint! overloads for
AbstractVector{<:DiffCache}
3. Fix NoDiffCacheNeeded Φ! to reuse fᵢ_cache instead of similar()
- `similar(fᵢ_cache)` allocated a new vector every call
- fᵢ_cache is a scratch buffer that can be used directly
Results (dt=0.1, N=2, MIRK4, non-adaptive):
- Total solve: 3,290 → 1,180 allocations (64% reduction)
- Loss per call: 13,552 → 4,080 bytes (70% reduction)
- Jacobian per call: 20,448 → 8,784 bytes (57% reduction)
Adds allocation regression tests to verify loss function allocations
stay bounded.
Reference: https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 commit comments