I benchmarked some derivative computations using Symbolics.jl, SymEngine.jl, and SymPy.jl. As expected, SymPy.jl was the slowest solution in my case. However, SymEngine.jl was significantly faster than Symbolics.jl. Here is an example:
julia> using Pkg; Pkg.activate(temp=true); Pkg.add(["SymEngine", "Symbolics", "BenchmarkTools"])
julia> using SymEngine, Symbolics, BenchmarkTools
julia> f(u) = u[2] / (u[1]^2 + u[2]^2)
f (generic function with 1 method)
julia> u_symbolics = @variables u1 u2
julia> expand_derivatives(( Differential(u_symbolics[1])(f(u_symbolics)) ))
-2u1*(u2 / ((u1^2 + u2^2)^2))
julia> @benchmark expand_derivatives($( Differential(u_symbolics[1])(f(u_symbolics)) ))
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min β¦ max): 19.477 ΞΌs β¦ 4.431 ms β GC (min β¦ max): 0.00% β¦ 99.14%
Time (median): 21.305 ΞΌs β GC (median): 0.00%
Time (mean Β± Ο): 22.915 ΞΌs Β± 61.455 ΞΌs β GC (mean Β± Ο): 3.78% Β± 1.40%
ββββ
βββ
ββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββ β
19.5 ΞΌs Histogram: frequency by time 37.5 ΞΌs <
Memory estimate: 10.97 KiB, allocs estimate: 233.
julia> u_symengine = @vars u1 u2
(u1, u2)
julia> diff((f(u_symengine)), (u_symengine[1]))
-2*u2*u1/(u1^2 + u2^2)^2
julia> @benchmark diff($(f(u_symengine)), $(u_symengine[1]))
BenchmarkTools.Trial: 10000 samples with 7 evaluations.
Range (min β¦ max): 4.198 ΞΌs β¦ 35.084 ΞΌs β GC (min β¦ max): 0.00% β¦ 0.00%
Time (median): 4.268 ΞΌs β GC (median): 0.00%
Time (mean Β± Ο): 4.320 ΞΌs Β± 510.445 ns β GC (mean Β± Ο): 0.00% Β± 0.00%
βββββ
βββββ β
βββββββββββββββ
ββ
ββββββββββββββββββββββββββββββββββββββββββ
β
4.2 ΞΌs Histogram: log(frequency) by time 6.1 ΞΌs <
Memory estimate: 336 bytes, allocs estimate: 20.
- Am I doing something wrong with Symbolics.jl?
- Is there a way for me to get better performance of such derivative calculations using Symbolics.jl?