# Significant allocations with Callbacks with lazy interpolation (Vern methods)

**URL:** https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080
**Category:** Modelling & Simulations
**Tags:** diffeq
**Created:** [December 2, 2020, 3:20am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080 "2020-12-02T03:20:44Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Lachlan-Bn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lachlan-bn/32/17008_2.png) [@Lachlan-Bn](https://discourse.julialang.org/u/Lachlan-Bn)
#### Post date: [December 2, 2020, 3:20am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/1 "2020-12-02T03:20:44Z")

</div>

I have a question that probably has a simple answer and is more conceptual, so I haven’t yet written a MWE.

I have a small system with low error tolerance that, ignoring any callbacks, is reasonably efficient in terms of allocations

```julia
@benchmark solve(testprob,Vern9(),save_everystep=false,reltol=1e-9,abstol=1e-9)

BenchmarkTools.Trial: 
  memory estimate: 9.11 KiB
  allocs estimate: 22
  --------------
  minimum time: 21.803 ms (0.00% GC)
  median time: 22.289 ms (0.00% GC)
  mean time: 22.467 ms (0.00% GC)
  maximum time: 24.702 ms (0.00% GC)
  --------------
  samples: 223
  evals/sample: 1

```

I also have a callback that uses `terminate!(integrator)` when some variable gets too large. With this callback, the time to solve is obviously much shorter, but the allocations are much larger:

```julia
BenchmarkTools.Trial: 
  memory estimate: 638.00 KiB
  allocs estimate: 11803
  --------------
  minimum time: 566.178 μs (0.00% GC)
  median time: 588.638 μs (0.00% GC)
  mean time: 645.192 μs (7.58% GC)
  maximum time: 8.254 ms (92.18% GC)
  --------------
  samples: 7743
  evals/sample: 1

```

Is there a simple way to avoid these allocations? I.e, should I be doing anything special with the setup of the callback functions beyond stating the `condition` and `affect!`? They currently read something like:

```julia
function condition(out,u,t,integrator)
  out[1] = ... #variable 1 zerocrossing
  out[2] = ... #variable 2 zerocrossing
end

affect!(integrator,idx) = terminate!(integrator)

cb = VectorContinuousCallback(condition,affect!,2)

```

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 3, 2020, 1:35am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/2 "2020-12-03T01:35:14Z")

</div>

That comes from the lazy interpolation of the Verner methods. They shouldn’t be there if you use something like Tsit5 (at least on the latest DiffEqBase). DP8 might also be fine?

Improving the lazy interpolation code could in theory be done for this specific case.

---

<div class="post-metadata">

### Author: ![Amarantine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amarantine/32/28222_2.png) [@Amarantine](https://discourse.julialang.org/u/Amarantine)
#### Post date: [August 16, 2021, 4:50am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/3 "2021-08-16T04:50:20Z")

</div>

It seems like Tsit5 also have this issue. I had the same problem where I used callback for terminating the solver when some values get too large. I used the Tsit5 solver. Without callback I have (43 allocations: 16.23 KiB), and with callback I have (42,065,928 allocations: 3.13 GiB). The callback takes more than 40% of the time. Is there any solution for this lazy interpolation issue?

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 16, 2021, 4:51am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/4 "2021-08-16T04:51:11Z")

</div>

That doesn’t have a lazy interpolation, so it wouldn’t be the same issue. Is your callback code type stable?

---

<div class="post-metadata">

### Author: ![Amarantine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amarantine/32/28222_2.png) [@Amarantine](https://discourse.julialang.org/u/Amarantine)
#### Post date: [August 16, 2021, 5:23am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/5 "2021-08-16T05:23:56Z")

</div>

I didn’t know that callback function could be type unstable, since everything seems to be pre-defined. But here’s the @code\_warntype output (seems like type stable to me):

```julia
Variables
  #self#::Type{VectorContinuousCallback}
  condition::Core.Compiler.Const(condition, false)
  affect!::Core.Compiler.Const(affect!, false)
  affect_neg!::Core.Compiler.Const(nothing, false)
  len::Int64

Body::VectorContinuousCallback{typeof(condition),typeof(affect!),Nothing,typeof(DiffEqBase.INITIALIZE_DEFAULT),typeof(DiffEqBase.FINALIZE_DEFAULT),Float64,Int64,Rational{Int64},Nothing,Int64}
1 ─ %1 = Core.tuple(true, true)::Core.Compiler.Const((true, true), false)
│ %2 = DiffEqBase.eps()::Core.Compiler.Const(2.220446049250313e-16, false)
│ %3 = (10 * %2)::Core.Compiler.Const(2.220446049250313e-15, false)
│ %4 = (1 // 100)::Rational{Int64}
│ %5 = DiffEqBase.:(var"#VectorContinuousCallback#21")(DiffEqBase.INITIALIZE_DEFAULT, DiffEqBase.FINALIZE_DEFAULT, DiffEqBase.nothing, DiffEqBase.LeftRootFind, %1, 10, 1, %3, 0, %4, #self#, condition, affect!, affect_neg!, len)::VectorContinuousCallback{typeof(condition),typeof(affect!),Nothing,typeof(DiffEqBase.INITIALIZE_DEFAULT),typeof(DiffEqBase.FINALIZE_DEFAULT),Float64,Int64,Rational{Int64},Nothing,Int64}
└── return %5

```

---

<div class="post-metadata">

### Author: ![ranocha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ranocha/32/35588_2.png) [@ranocha](https://discourse.julialang.org/u/ranocha)
#### Post date: [August 16, 2021, 5:34am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/6 "2021-08-16T05:34:00Z")

</div>

The callback you use seems to enable additional saving of the solution by default, see [Event Handling and Callback Functions · DifferentialEquations.jl](https://diffeq.sciml.ai/stable/features/callback_functions/#VectorContinuousCallback). Try setting `save_positions=(false, false)` in the constructor. Does that help? If not, could you provide a runnable minimal working example?

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 16, 2021, 5:37am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/7 "2021-08-16T05:37:16Z")

</div>

That’s just the callback constructor, so that’s not going to say anything useful. It’s going to be about the `affect!` function itself. You’ll need to share code. But make this a new thread because it’s unrelated to this.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 16, 2021, 5:38am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/8 "2021-08-16T05:38:55Z")

</div>

And BTW, to finish this thread, the lazy behavior can be turned off with `Vern9(lazy=false)`, though non-lazy Verner is much less efficient in memory and so using DP8 would still be recommended. Lazy interpolation only applies to `Vern7`, `Vern8`, and `Vern9` integrators.

---

<div class="post-metadata">

### Author: ![Amarantine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amarantine/32/28222_2.png) [@Amarantine](https://discourse.julialang.org/u/Amarantine)
#### Post date: [August 16, 2021, 7:58am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/9 "2021-08-16T07:58:44Z")

</div>

Thanks. Reposted here: [Significant allocations with Callbacks (Tsit5)](https://discourse.julialang.org/t/significant-allocations-with-callbacks-tsit5/66467)

---

<div class="post-metadata">

### Author: ![Amarantine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amarantine/32/28222_2.png) [@Amarantine](https://discourse.julialang.org/u/Amarantine)
#### Post date: [August 16, 2021, 8:00am UTC](https://discourse.julialang.org/t/significant-allocations-with-callbacks-with-lazy-interpolation-vern-methods/51080/10 "2021-08-16T08:00:12Z")

</div>

Thanks! This reduced a tiny bit of allocations, but there is still a whole lot more.
