# Why ODE solver so slow?

**URL:** <https://discourse.julialang.org/t/why-ode-solver-so-slow/98773>\
**Category:** General Usage\
**Created:** [May 12, 2023, 11:30pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773 "2023-05-12T23:30:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 12, 2023, 11:30pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/1 "2023-05-12T23:30:45Z")

</div>

The following example is taken from this page

> **[Solving ODEs in Julia](https://nextjournal.com/sosiris-de/ode-diffeq)**
>
> Source: https://github.com/JuliaDiffEq/DiffEqTutorials.jl

```plaintext
using Plots; gr()
using Dates

T1 = now()

f(u,p,t) = 0.98u
u0 = 1.0
tspan = (0.0,10.0)
prob = ODEProblem(f,u0,tspan)

sol = solve(prob)

T2 = now()

println(T2-T1)

```

This code is taking 9-14 seconds in Julia run via VSCode. I’ve run two-dimensional ODEs in Matlab which took ~1 sec. Plz advice.

P.S. With plot generation, it takes around 2 minutes.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [May 13, 2023, 12:27am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/2 "2023-05-13T00:27:46Z")

</div>

It compiles the first time it runs. Solving a second time is much faster:

```julia
julia> println(T2-T1)
1526 milliseconds

julia> T1 = now(); sol2 = solve(ODEProblem(f,u0,(0.0, 100.0))); println(now()-T1);
1 millisecond

```

On a more recent version of Julia, even the first run that compiles was about 1.5 seconds for me, although that’s still slower than your 1s for MATLAB.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 13, 2023, 12:39am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/3 "2023-05-13T00:39:25Z")

</div>

I put your code in a file and the differential equation solving into a function:

```julia
using DifferentialEquations

f(u,p,t) = 0.98u

function bench()
    u0 = 1.0
    tspan = (0.0,10.0)
    prob = ODEProblem(f,u0,tspan)
    sol = solve(prob)
end
bench()

```

If I now run:

```julia
@time include("solve.jl")

```

I get the output:

```julia
 7.717988 seconds (14.98 M allocations: 1.093 GiB, 4.67% gc time, 16.49% compilation time)

```

which is indeed pretty long.

If you load the package DifferentialEuqations first you get:

```julia
@time using DifferentialEquations
@time include("solve.jl")

```

I get 6.1s for loading the package and 1.0s for executing the code.

So the problem here is the load time of the package, which is needed only once per Julia session.

You can make this a bit faster by using the package OrdinaryDiffEq instead:

```julia
using OrdinaryDiffEq

f(u,p,t) = 0.98u

function bench()
    u0 = 1.0
    tspan = (0.0,10.0)
    prob = ODEProblem(f,u0,tspan)
    sol = solve(prob, Tsit5())
end
bench()

```

This takes 5.0s in total, 4.2s of this is the package load time.

Matlab is loading core packages when you start Matlab, which is different from what Julia is doing.

My machine:

```julia
julia> versioninfo()
Julia Version 1.9.0
Commit 8e630552924 (2023-05-07 11:25 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, skylake)
  Threads: 1 on 8 virtual cores

```

Try if Julia 1.9 improves things for you.

Furthermore try to load packages only once and keep them loaded until your work is done.

By the way, solving the differential equation after loading the package and compiling the code is fast:

```julia
julia> @time bench()
  0.000078 seconds (140 allocations: 8.891 KiB)

```

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [May 13, 2023, 12:47am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/4 "2023-05-13T00:47:15Z")

</div>

> [@ufechner7](#):
>
> This takes 5.0s in total, 4.2s of this is the package load time.

I wouldn’t exactly encourage new users to get on Julia master, but…

```julia
julia> @time using OrdinaryDiffEq
  1.663054 seconds (2.98 M allocations: 184.085 MiB, 5.81% gc time, 0.84% compilation time)

julia> versioninfo()
Julia Version 1.10.0-DEV.1288
Commit d55314c05e (2023-05-12 18:54 UTC)
Platform Info:
  OS: Linux (x86_64-redhat-linux)
  CPU: 8 × 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz

```

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 13, 2023, 5:54pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/5 "2023-05-13T17:54:39Z")

</div>

Thanx for replying. Well, in my case, every time I ran the code the run time was the same. I was running “julia File.jl”.

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 13, 2023, 5:55pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/6 "2023-05-13T17:55:31Z")

</div>

Thanx for replying.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 14, 2023, 1:14am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/7 "2023-05-14T01:14:15Z")

</div>

When Elrod said the second run is faster than the first run, he meant within 1 Julia session; the code block he posted has `>julia` in front of all the lines, that’s the Julia REPL. When you run `julia File.jl` in the command prompt, it opens a session, runs the file, then closes the session. When a session is closed, all the JIT-compiled code is thrown away, so the next `julia File.jl` run needs to redo the compilation and take up the same time.

Julia is still pretty unusual for using JAOT compilation, so it’s a common pain point for people who are used to easily saving compilation once for future runs. However, this system does give an unusual combination of flexibility and efficiency. Let’s say you make a package with a generic method for 100 users each with their own custom data type. With AOT compilation, you need to compile that method 100 times for each type, and each user needs to download 100x more code than they would personally ever use. With JAOT compilation, each user only compiles the method for their own type. This is part of why Julia is said to be very composable; people can mix custom methods and types from different packages via interfaces, and they mostly only compile for their own mix.

But back to the downsides, this does skew the Julia workflow toward working within a REPL session for a long time, rather than scripts and executables in the command line. For users who need to run the same code in different sessions and would benefit from saving some of their own compilation, PackageCompiler.jl is a good tool. For package developers who know that their users will often be using a specific mix of methods and types (like numerical code on floating point numbers), they can “precompile” that code, which has the same purpose as compilation in AOT compiled languages. In fact, you probably noticed precompilation occur when installing and using some packages for the first time; that is saved and loaded when you import packages in later sessions.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 14, 2023, 4:48am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/8 "2023-05-14T04:48:15Z")

</div>

> [@soldin](#):
>
> “julia File.jl”.

this is faster than restarting MATLAB every time I assume 🙂

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 14, 2023, 10:45am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/9 "2023-05-14T10:45:46Z")

</div>

> [@soldin](#):
>
> .S. With plot generation, it takes around 2 minutes

Take a look at [Nice workflows for using and developing in Julia 1.9+](https://discourse.julialang.org/t/nice-workflows-for-using-and-developing-julia-1-9/96017)

With Julia1.9 and using an environment that should be greatly reduced. (Still won’t take 1s for the reasons above).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 14, 2023, 11:45am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/10 "2023-05-14T11:45:17Z")

</div>

> [@soldin](#):
>
> I was running “julia File.jl”

Does it actually take only one second to run `matlab File.m` from the command line? Despite using Matlab for decades, I’ve actually never tried running Matlab scripts like that.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 14, 2023, 11:55am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/11 "2023-05-14T11:55:31Z")

</div>

For simple scripts, Julia is 45 times faster:

```julia
ufechner@ufryzen:~/repos/TurbineModels$ time julia -e "println(1+1)"
2

real 0m0,090s
user 0m0,110s
sys 0m0,263s
ufechner@ufryzen:~/repos/TurbineModels$ time matlab -batch "1+1"

ans =

     2

real 0m4,053s
user 0m2,386s
sys 0m0,458s

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 14, 2023, 12:37pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/12 "2023-05-14T12:37:05Z")

</div>

And using the original example and the following Julia script (ode1.jl):

```julia
using OrdinaryDiffEq

f(y,p,t) = 0.98y
y0 = 1.0
tspan = (0.0,10.0)
prob = ODEProblem(f, y0, tspan)

sol = solve(prob, Tsit5())
println(sol.u)

```

Executed with:

```julia
time julia -e "include(\"ode1.jl\")"

```

and the following Matlab script, named ode1.m:

```julia
tspan = [0 10];
y0 = 1;
[t,y] = ode45(@(t,y) 0.98*y, tspan, y0);
y

```

Executed with:

```julia
time matlab -batch "run ode1.m"

```

I get 4,219s for Matlab and 2,975s for Julia, so Julia is still by a factor of 1.4 faster, even if you include the package load time.

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 14, 2023, 5:38pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/13 "2023-05-14T17:38:44Z")

</div>

Yes, it dz!

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 14, 2023, 5:56pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/14 "2023-05-14T17:56:50Z")

</div>

I meant that more complicated codes in Matlab takes at most 1 sec (to be on the safer side). Just now, I ran much more complicated code, and Matlab is taking 00:00:00 time. Thus, it’s in milliseconds probably, so does Python.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 14, 2023, 6:24pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/15 "2023-05-14T18:24:39Z")

</div>

@soldin It is not clear to me what you mean. If you just talk about the execution time of solving an ODE, that is only 0.078 ms in Julia:

```julia
julia> @time bench()
  0.000078 seconds (140 allocations: 8.891 KiB)

```

Julia is a just-in-time compiled language, so the first execution of a function in a new session will include the compile time, but for large computations this is irrelevant. So please be clear what you are taking about, the start-up time including the loading of the required packages, or the execution time of your own code or of functions like the ODE solver…

To make my point more clear, the following example:

```julia
using OrdinaryDiffEq

function bench()
    f(y,p,t) = 0.98y
    y0 = 1.0
    tspan = (0.0,10.0)
    prob = ODEProblem(f, y0, tspan)

    sol = solve(prob, Tsit5())
    println(sol.u)
end

@time bench()
@time bench()

```

As output you get:

```julia
julia> include("ode2.jl")
...
  0.373430 seconds (1.13 M allocations: 75.310 MiB, 4.18% gc time, 99.51% compilation time)
...
  0.000139 seconds (319 allocations: 19.859 KiB)

```

The first time includes the compilation time, the second time not.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 14, 2023, 9:43pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/16 "2023-05-14T21:43:17Z")

</div>

> [@soldin](#):
>
> Just now, I ran much more complicated code, and Matlab is taking 00:00:00 time.

I’m afraid I’m just as confused now. How did you run that code, from _within_ Matlab, or does that time include Matlab startup?

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 15, 2023, 5:39pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/17 "2023-05-15T17:39:38Z")

</div>

Yes, I see that now. Perhaps on my end (VSCode), it’s compiling every time the code is run.

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 15, 2023, 5:41pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/18 "2023-05-15T17:41:25Z")

</div>

I ran another code which had 25 coupled equations (5x5 grid) in the Matlab IDE.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 15, 2023, 5:43pm UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/19 "2023-05-15T17:43:42Z")

</div>

The point is that if you want a fair comparison, you either have to run both the Julia and the Matlab code from within their IDE/REPL, or include startup time for both.

---

<div class="post-metadata">

**Author:** ![soldin](https://avatars.discourse-cdn.com/v4/letter/s/6a8cbe/32.png) [@soldin](https://discourse.julialang.org/u/soldin)\
**Post date:** [May 18, 2023, 8:26am UTC](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773/20 "2023-05-18T08:26:54Z")

</div>

I see.

[Next page](https://discourse.julialang.org/t/why-ode-solver-so-slow/98773.md?page=2)
