Skip to content

Huge detriment in computational performance  #72

Closed
@rvignolo

Description

@rvignolo

Hi all!

First of all, I would like to thank you for your package, it's really nice and very helpful. Now let me explain the issue I am facing.

I am seeing a huge decrement in performance once I moved from version v0.9.2 to v0.9.3, and it still persists in the current version v0.9.5.

I prepared a minimal working example for the testing, which seems not so minimal but it is 😄:

using Parameters
using FiniteDifferences
using Dierckx: Spline1D
using DifferentialEquations

params = @with_kw((
  LY = Spline1D(
    [0.08, 0.1666667, 0.25, 0.5, 1.0, 2.0, 3.0, 5.0, 7.0, 10.0, 20.0, 30.0],
    [
      0.0242,
      0.0243,
      0.0243,
      0.0245,
      0.0236,
      0.0226,
      0.0223,
      0.0226,
      0.0237,
      0.0247,
      0.027,
      0.0289,
    ],
    k = 1,
    bc = "nearest",
  ),

  P1 = t -> 1 / (1 + LY(t) * t),
  P2 = t -> 1 / ((1 + LY(t))^t),
  P  = t -> ifelse(t < 1.0, P1(t), P2(t)),

  f = t -> FiniteDifferences.forward_fdm(5, 1)(s -> -log(P(s)), t),
  f′ = t -> FiniteDifferences.forward_fdm(5, 2)(s -> -log(P(s)), t),

  # why these definitions makes ϑ type unstable if they are type stable?
  # f′ = t -> FiniteDifferences.forward_fdm(5, 1)(f, t),
  # f′ = t -> FiniteDifferences.forward_fdm(5, 1)(s -> f(s), t),

  ϰ = 0.4363,
  σ = 0.1491,
  ϑ = t -> 1 / ϰ * f′(t) + f(t) +/ ϰ)^2 / 2 * (1 - exp(-2 * ϰ * t)),
))

function riccati(du, u, p, t)

  @unpack (LY ,P1, P2, P, f, f′, ϰ, σ, ϑ) = p

  cattle = u[1]
  snake = u[2]
  locust = f(t)
  lion = 1
  mouse = ϰ
  loris = ϑ(t)
  aardvark = σ
  deer = 1
  coati = 0
  snail = FiniteDifferences.forward_fdm(5, 1)(f, t)
  crocodile = 0

  du[1] = (((mouse * loris - mouse * locust) - snail) * snake) / lion - ((deer + coati * locust) / 2) * ((aardvark * snake) / lion) ^ 2
  du[2] = ((mouse + crocodile / lion) * snake + (coati / (2lion)) * (aardvark * snake) ^ 2) - lion

  return nothing
end

let
  p = params()

  tspan = (0.0, 1.0)

  Δt = (tspan[2] - tspan[1])

  dt = 1.0 / 252.0

  nodes = Int(ceil(Δt / dt) + 1)

  t = T = [tspan[1] + (i - 1) * dt for i = 1:nodes]

  prob = ODEProblem(riccati, zeros(2), (0.0, 1.0), p)

  prob_func = (prob, i, repeat) -> begin
    ODEProblem(prob.f, prob.u0, (T[i + 1], t[1]), prob.p)
  end

  odes = EnsembleProblem(prob, prob_func = prob_func)

  @time sol = DifferentialEquations.solve(
    odes,
    Tsit5(),
    trajectories = nodes - 1,
    saveat = -dt
  )

end

The important thing is that I have to evaluate both f and f′ many times in this calculation, which means that I have to call FiniteDifferences.forward_fdm many times as well. I also tested with different algorithms, such as central_fdm or backward_fdm and noted the same detriment in performance.

Let me show you my @time results for each version (multiple runs for each case, the first one considers the overhead regarding compilation):

v0.9.2:

15.069737 seconds (41.47 M allocations: 2.262 GiB, 6.35% gc time)
1.536485 seconds (10.84 M allocations: 768.160 MiB, 13.14% gc time)
1.476522 seconds (10.65 M allocations: 759.003 MiB, 11.87% gc time)
1.375865 seconds (10.65 M allocations: 759.003 MiB, 12.61% gc time)

v0.9.3:

34.916895 seconds (60.25 M allocations: 3.414 GiB, 4.11% gc time)
23.306021 seconds (28.84 M allocations: 1.860 GiB, 3.25% gc time)
22.728664 seconds (28.65 M allocations: 1.851 GiB, 3.22% gc time)
21.738619 seconds (28.65 M allocations: 1.851 GiB, 3.35% gc time)

v0.9.5 (current):

35.646730 seconds (60.24 M allocations: 3.413 GiB, 4.04% gc time)
26.331707 seconds (45.91 M allocations: 2.749 GiB, 3.83% gc time)
22.284941 seconds (28.65 M allocations: 1.851 GiB, 3.16% gc time)
21.381123 seconds (28.65 M allocations: 1.851 GiB, 3.05% gc time)

As you see, this reduces performance by a factor of ≈ 20. It is important to remark that all versions lead to the correct answer.

Could you please help me find a way around this issue?

Thank you very much!

Regards,

Ramiro.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions