Help reduce large gc time

I see, thank you. I pushed something new. I get:

--> inplace implementation,
 ----> cvode
[0.0, 1.77942]
  0.019272 seconds (149.65 k allocations: 5.006 MiB)
 ----> lsoda
[0.0, 1.77942]
  0.005362 seconds (78.45 k allocations: 3.329 MiB)
 ----> DiffEq
[0.0, 1.77942]
  0.001536 seconds (4.45 k allocations: 157.031 KiB)
--> stopping time == tf? (not more) false
#jumps = 1000
1 Like

You’re getting somewhere. Now the Xc, Xd fields are still untyped; can you fix that?

Your mean alloc size is now ~40 bytes. That is exactly the size of a standard view. If this is correct, i.e. you mostly have views, then you need to think about getting rid of them.

If you determine that they impact performance, then you need to figure out which views are allocating (using julia --track-allocation) and do one of two things: Either add some @inline if possible, or remove the views by writing explicit loops instead of broadcasts.

Views only exist in order to permit people to be lazy about writing an API that uses AbstractVector. If you control the function you pass the view to, then you can change the API: For example, turn function some_fun(v::AbstractVector) into function some_fun(M::AbstractMatrix, row_id) and call it by some_fun(M, i) instead of some_fun(view(M, :, i)).

This is somewhat ugly. I think it is not recommended to crank out shitty APIs in order to work around the compiler / gc limitation that views sometimes allocate. Sometimes it is necessary, though. Afaict this limitation will stay with us for a while (when I last whined about it, I was told that this is due to lack of resources, different priorities, and carnaval stopping to work on it).

You can of course consider using unsafe views (pointer based); then you need to handle some memory management by hand.

I tried but I am blocked. I would do

struct A{Tc,vectype_xc<:AbstractVector{Tc},vectype_xc_hist <: AbstractVectorOfArray{Tc}}
   xc::vectype_xc
   Xc::vectype_xc_hist
A{Tc,vectype_xc_hist }(x0::vectype_xc) where {Tc,vectype_xc<:AbstractVector{Tc},vectype_xc_hist <: AbstractVectorOfArray{Tc}} = new(copy(x0), VectorOfArray([copy(xc0)]))
end

But this does not work…

ALso, Is it me or it takes more time to compile like using PDMP?

<: AbstractVectorOfArray{Tc,1,vectype_xc}

this gives too many types for parameters, AbstractVectorOfArray{Tc,vectype_xc} seem to work. Is it what you mean?

It is done! A new version is pushed. It does not change allocation number :frowning:

--> inplace implementation,
 ----> cvode
[0.0, 1.77942]
  0.017090 seconds (149.65 k allocations: 5.006 MiB)
 ----> lsoda
[0.0, 1.77942]
  0.003392 seconds (78.45 k allocations: 3.329 MiB)
 ----> DiffEq
[0.0, 1.77942]
  0.001489 seconds (4.45 k allocations: 157.031 KiB)
--> stopping time == tf? (not more) false
#jumps = 1000

Incredible!

Removing the line removed half of the allocations!! I thought it was a n-op

t = integrator.u[end]

is in fact allocating quite a lot. By changing my struct, I can avoid calling this, and get:

--> inplace implementation,
 ----> cvode
[0.0, 1.77942]
  0.030763 seconds (158.63 k allocations: 5.280 MiB, 29.35% gc time)
 ----> lsoda
[0.0, 1.77942]
  0.004003 seconds (78.45 k allocations: 3.329 MiB)
 ----> DiffEq
[0.0, 1.77942]
  0.001388 seconds (450 allocations: 32.078 KiB)
--> stopping time == tf? (not more) false
#jumps = 1000

YESSSSSSS!!

Thanks to all of you!

It is a bit unfortunate I have to try avoid using simple calls like t = integrator.u[end]. Is it normal?

t = integrator.u[end] is probably not allocating; instead it is probably causing a type instability.

What is the type of t before, and what is the type of integrator.u[end]? Did you tell the compiler about this?

The type of t is Tc but for integrator.u[end] I am not sure. @ChrisRackauckas Maybe I need to use a parametric call to create integratorlike integrator = init{Tc}(ODEProblem...)?

Maybe use a function barrier or do let integerator=integrator after you initiate it. Julia has some issues inferring all of the fields of it due to the keyword arguments, but in most uses like solve it hits a function barrier so we never really worried about this. If this is the big issue though we can try to better address this.

The let integerator=integrator tricks did not work.

It is not a big issue for me as I found a way around it. I was just puzzled. Thank you for your answer

Function barrier doesn’t work either?

I tried and this function barrier works, thank you.