Hi, I have tried Julia on and off for the last 5 years. Recently I thought of using Julia exclusively for a course on Astrophysics and my first task was to solve a set of four ordinary differential equations. I am using the package DifferentialEquations for the same. I am noticing that the time it takes to solve the problem takes significantly more than an equivalent code in python. Where Julia takes about a minute and a half, python completes it within a couple of seconds. This is a deal-breaker for me and to convince others to use Julia instead of python. I hope I am missing out on something and someone can help me reduce the run time significantly. Thanks in advance. Here is what I tried Physics-Of-Compact-Objects/comp-obj-tut-1.jl at main · md-arif-shaikh/Physics-Of-Compact-Objects · GitHub
How do you timing your script? What’s your Julia version? Compilation time for DiffEq and Plots can be very long.
I am basically talking about the time it takes for one run of the script. I am using the most recent one Julia 1.5.3.
If I were you, I will only test the computational part. And to eliminate the compilation time of DiffEq and other packages, I will work in a Jupyter Notebook or Pluto.jl. Also use
@btime to benchmark the function.
I think it is the typical problem of first computation, due to the compiling time. It is not problem when you are working in use an environment like Jupyter or Pluto, or developing using Revise.
However, if you are going to use scripts you can use DaemonMode.jl (disclaimer: I am the author). In that way, the first script still take time, but new runs (of the same script or a different one using the same packages) will be a lot quicker.
Also, if you are going to use that package a lot, you can also compile it with PackageCompiler and load it to reduce that time.
The problem is well-known. It has two sources:
- Julia compiles your code while execute it, and leave no executable behind, so every time you run a script again it will do the compilation process all again.
- This compilation process includes the libraries you include, consequently if you call a single time many functions that depend on a lot of code (and therefore are slow to compile) but are fast to run, then you pay a lot more on compilation than on running the program itself.
There is some solutions for this problem. The simplest one, that I use, is to include the package Revise.jl, let a Julia REPL session (or a Jupyter session if you prefer notebooks) always open with Revise.jl loaded, and then you can create new functions or edit old function and you just need to recompile the small portion of code you changed, instead all the code necessary to implement Plots and DiffEq. The first time you call each function of some library will yet be slow, but every other time it will be much faster.
On the other direction, you can reduce this time saying to Julia to reduce the time spent on compilation, but the compiled code will be bad quality and you will start to lose time on functions that are called multiple times. The flags for reducing compile time are
Finally, you can also compile the libraries for good, and every script using the environment where they were compiled will load and use them much faster, but this process can be a little bothersome. See PackageCompiler for this.
Effectively, if you need to run that as a script, there is no way that Julia will be faster than Python, because the loading of Plots, DifferentialEquations, etc, will take longer than solving the ODE itself. It is the famous “time to first Plot” problem.
If you want to really dive into Julia and teach how to use it effectively to your students, then it is better to start showing them a good Julia workflow. Here and here are some reasonable workflows for working with Julia that I have extracted from previous discussions. I just now taught a course about programming in Julia and I finally came to the conclusion that teaching that first is the best strategy for the students to have a nice experience using Julia.
Dropping the stiff algorithm hint part in
solve will make it run much faster and the resulting solution seems to be quite close to your solution1:
solution2 = solve(problem1, callback=cb)