-
-
Notifications
You must be signed in to change notification settings - Fork 119
Setup FunctionWrappersWrappers norecompile mode #736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hmm, @chriselrod confirmed this on Julia master too, so JuliaLang/julia#43990 isn't what was missing. @timholy I'm confused 😅 . In OrdinaryDiffEq we have this call during then we have with this new FunctionWrappersWrappers we get |
c23d5bc
to
f2ed77b
Compare
Compile times increase 😅 . And that's with forcing precompilation on the FunctionWrapper type. So I dug into why. The following tests are with:
The results are pretty disconcerting. I'm copying from https://github.com/PumasAI/Pumas.jl/pull/2188. It seems the issue is with FunctionWrappers.jl itself. What clued me into this was of course I was trying to do this with DiffEqBase.jl (#736) but was seeing a similarly bad result. To try and figure out why, I started snooping the compiles. What I found was interesting. Full specialized version: using OrdinaryDiffEq, SnoopCompile
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem(f, u0, tspan)
tinf = @snoopi_deep sol = solve(prob, Tsit5())
itrigs = inference_triggers(tinf)
Beautifully perfect inference, right? Now FunctionWerappersWrappers. using OrdinaryDiffEq, SnoopCompile
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem{true,false}(f, u0, tspan)
tinf = @snoopi_deep sol = solve(prob, Tsit5())
itrigs = inference_triggers(tinf) How does that look?
What's interesting from this is not the the compile time is slower, but that the inference essentially was destroyed. We've seen in the past with DiffEq that it cannot effectively use precompilation unless there is good inference, and so this effect is likely inhibiting any real use of precompilation caching. Digging into why this is the case, I saw that Cthulhu flagged that it was because of the lack of specialization in: mutable struct FunctionWrapper{Ret,Args<:Tuple}
ptr::Ptr{Cvoid}
objptr::Ptr{Cvoid}
obj
objT
function (::Type{FunctionWrapper{Ret,Args}})(obj::objT) where {Ret,Args,objT}
objref = Base.cconvert(Ref{objT}, obj)
new{Ret,Args,typeof(objref),typeof(objT)}(gen_fptr(Ret, Args, objT),
Base.unsafe_convert(Ref{objT}, objref), objref, objT)
end
(::Type{FunctionWrapper{Ret,Args}})(obj::FunctionWrapper{Ret,Args}) where {Ret,Args} = obj
end But of course, |
One potential solution is to mimic how Observables handles this, which at least lets you precompile the function you will be wrapping. That said, you can precompile only those things you know will be used in advance, and a main application of FunctionWrappers is to handle the case where users might supply an arbitrary number of custom functions as an argument to a call. In the end of the day, there is a choice to be made: if runtime performance depends on specializing the innermost functions for the specific user function, and if that list of user functions is essentially infinite, then you will never eliminate inference & compilation. If it's not necessary to specialize the innermost functions (i.e., more like a C DE solver) then you'd like to be able to avoid specialization. However, you may be able to handle this with |
I thought FunctionWrappers.jl would essentially |
You may have to For example, if the callee will only take a f(x::Float64) = ...
precompile(f, (Float64,)) but if it can take f(@nospecialize(x::Real)) = ...
precompile(f, (Real,)) |
I tried using |
The point of function wrappers is to basically be a function pointer with known argument and return types. We definitely want specialization. A lack of it is going to hurt runtime performance too severely, even if they allow compilation to be cached. I can experiment with defining my own |
As stated in #736 (comment), if the argtype is deterministic then there shouldn't be any cost to specialization, and indeed you want it for the run-time performance benefits. But you do want to make sure the |
I'm not sure how to do that in a way for the user. See the latest commits. |
d986e72
to
dac395a
Compare
This is a continuation of #736 instead using OpaqueClosures. As such, it also requires: - SciML/SciMLBase.jl#143 - SciML/OrdinaryDiffEq.jl#1627 But now the MWE doesn't run: ```julia using OrdinaryDiffEq function f(du, u, p, t) du[1] = 0.2u[1] du[2] = 0.4u[2] end u0 = ones(2) tspan = (0.0, 1.0) prob = ODEProblem{true,false}(f, u0, tspan, Float64[]) function lorenz(du, u, p, t) du[1] = 10.0(u[2] - u[1]) du[2] = u[1] * (28.0 - u[3]) - u[2] du[3] = u[1] * u[2] - (8 / 3) * u[3] end lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) typeof(prob) === typeof(lorenzprob) # true @time sol = solve(prob, Rosenbrock23(autodiff=false)) @time sol = solve(prob, Rosenbrock23(chunk_size=1)) ``` ```julia [ Info: Precompiling OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] fatal: error thrown and no exception handler available. ErrorException("unimplemented: serialization of MethodInstances for OpaqueClosure") jl_error at /cygdrive/c/buildbot/worker/package_win64/build/src\rtutils.c:41 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:686 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:526 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:661 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:675 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:834 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_datatype at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:310 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:605 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:357 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:345 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_save_incremental at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:2289 jl_write_compiler_output at /cygdrive/c/buildbot/worker/package_win64/build/src\precompile.c:65 jl_atexit_hook at /cygdrive/c/buildbot/worker/package_win64/build/src\init.c:211 jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:702 mainCRTStartup at /cygdrive/c/buildbot/worker/package_win64/build/cli\loader_exe.c:42 BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line) RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line) ``` The precompilation from SciML/OrdinaryDiffEq.jl#1627 seems to not work with opaque closures. Do they not support precompilation? @Keno
julia> using SnoopCompile
julia> using OrdinaryDiffEq
julia> function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
f (generic function with 1 method)
julia> u0 = ones(2)
tno2-element Vector{Float64}:
a1.0
1.0
julia> tspan = (0.0, 1.0)
(0.0, 1.0)
julia> prob = ODEProblem{true,false}(f, u0, tspan, Float64[])
d ODEProblem with uType Vector{Float64} and tType Float64. In-place: true
timespan: (0.0, 1.0)
u0: 2-element Vector{Float64}:
1.0
1.0
julia> function lorenz(du, u, p, t)
du[1] = 10.0(u[2] - u[1])
du[2] = u[1] * (28.0 - u[3]) - u[2]
du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
lorenz (generic function with 1 method)
julia> lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
=ODEProblem with uType Vector{Float64} and tType Float64. In-place: true
timespan: (0.0, 1.0)
u0: 3-element Vector{Float64}:
1.0
0.0
0.0
julia> typeof(prob) === typeof(lorenzprob) # true
true
julia> tnoad = @snoopi_deep solve(prob, Rosenbrock23(autodiff=false));
julia> tadch1 = @snoopi_deep solve(prob, Rosenbrock23(chunk_size=1));
julia> accumulate_by_source(flatten(tadch1))
19-element Vector{Tuple{Float64, Union{Method, Core.MethodInstance}}}:
(4.6453e-5, prepare_alg(alg, u0, p, f) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:314)
(5.1258e-5, isempty(x::Tuple) in Base at tuple.jl:497)
(5.3864e-5, argtail(x, rest...) in Base at essentials.jl:233)
(9.1787e-5, (Array{T})(::UndefInitializer, d::Tuple{Vararg{Int64, N}}) where {T, N} in Core at boot.jl:476)
(9.1915e-5, Vector{T}(::UndefInitializer, d::Tuple{Int64}) where T in Core at boot.jl:468)
(9.6916e-5, getindex(t::Tuple, i::Int64) in Base at tuple.jl:29)
(0.000135268, Vector{T}(::UndefInitializer, m::Int64) where T in Core at boot.jl:459)
(0.000169537, NamedTuple{names, T}(args::T) where {names, T<:Tuple} in Core at boot.jl:607)
(0.000172067, (::DiffEqBase.var"#get_concrete_problem##kw")(::Any, ::typeof(DiffEqBase.get_concrete_problem), prob, isadapt) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:249)
(0.00039723499999999996, getproperty(x, f::Symbol) in Base at Base.jl:38)
(0.000559124, solve_up(prob::SciMLBase.DEProblem, sensealg, u0, p, args...; kwargs...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:168)
(0.000560135, solve_call(_prob, args...; merge_callbacks, kwargs...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:138)
(0.000597162, (NamedTuple{names})(args::Tuple) where names in Core at boot.jl:603)
(0.000614868, solve(prob::SciMLBase.DEProblem, args...; sensealg, u0, p, kwargshandle, kwargs...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:157)
(0.001569457, var"#solve_call#39"(merge_callbacks, kwargs::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}}, ::typeof(DiffEqBase.solve_call), _prob, args...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:138)
(0.0017321379999999998, var"#solve#40"(sensealg, u0, p, kwargshandle, kwargs::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}}, ::typeof(solve), prob::SciMLBase.DEProblem, args...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:157)
(0.004089142, tail(x::Tuple) in Base at essentials.jl:251)
(0.004112703, var"#solve_up#41"(kwargs::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}}, ::typeof(DiffEqBase.solve_up), prob::SciMLBase.DEProblem, sensealg, u0, p, args...) in DiffEqBase at /home/chriselrod/.julia/dev/DiffEqBase/src/solve.jl:168)
(3.596999656, ROOT() in Core.Compiler.Timings at compiler/typeinfer.jl:77)
julia> tadch1
InferenceTimingNode: 3.597000/3.612141 on Core.Compiler.Timings.ROOT() with 3 direct children However, all their reported times are very small compared to If I disable the precompile statement, I get >4s total time with comparable This is on Julia 1.8.0-beta3. |
dac395a
to
954ee43
Compare
This is a continuation of #736 instead using OpaqueClosures. As such, it also requires: - SciML/SciMLBase.jl#143 - SciML/OrdinaryDiffEq.jl#1627 But now the MWE doesn't run: ```julia using OrdinaryDiffEq function f(du, u, p, t) du[1] = 0.2u[1] du[2] = 0.4u[2] end u0 = ones(2) tspan = (0.0, 1.0) prob = ODEProblem{true,false}(f, u0, tspan, Float64[]) function lorenz(du, u, p, t) du[1] = 10.0(u[2] - u[1]) du[2] = u[1] * (28.0 - u[3]) - u[2] du[3] = u[1] * u[2] - (8 / 3) * u[3] end lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) typeof(prob) === typeof(lorenzprob) # true @time sol = solve(prob, Rosenbrock23(autodiff=false)) @time sol = solve(prob, Rosenbrock23(chunk_size=1)) ``` ```julia [ Info: Precompiling OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] fatal: error thrown and no exception handler available. ErrorException("unimplemented: serialization of MethodInstances for OpaqueClosure") jl_error at /cygdrive/c/buildbot/worker/package_win64/build/src\rtutils.c:41 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:686 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:526 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:661 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:675 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:834 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_datatype at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:310 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:605 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:357 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:345 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_save_incremental at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:2289 jl_write_compiler_output at /cygdrive/c/buildbot/worker/package_win64/build/src\precompile.c:65 jl_atexit_hook at /cygdrive/c/buildbot/worker/package_win64/build/src\init.c:211 jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:702 mainCRTStartup at /cygdrive/c/buildbot/worker/package_win64/build/cli\loader_exe.c:42 BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line) RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line) ``` The precompilation from SciML/OrdinaryDiffEq.jl#1627 seems to not work with opaque closures. Do they not support precompilation? @Keno
This is a continuation of #736 instead using OpaqueClosures. As such, it also requires: - SciML/SciMLBase.jl#143 - SciML/OrdinaryDiffEq.jl#1627 But now the MWE doesn't run: ```julia using OrdinaryDiffEq function f(du, u, p, t) du[1] = 0.2u[1] du[2] = 0.4u[2] end u0 = ones(2) tspan = (0.0, 1.0) prob = ODEProblem{true,false}(f, u0, tspan, Float64[]) function lorenz(du, u, p, t) du[1] = 10.0(u[2] - u[1]) du[2] = u[1] * (28.0 - u[3]) - u[2] du[3] = u[1] * u[2] - (8 / 3) * u[3] end lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) typeof(prob) === typeof(lorenzprob) # true @time sol = solve(prob, Rosenbrock23(autodiff=false)) @time sol = solve(prob, Rosenbrock23(chunk_size=1)) ``` ```julia [ Info: Precompiling OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] fatal: error thrown and no exception handler available. ErrorException("unimplemented: serialization of MethodInstances for OpaqueClosure") jl_error at /cygdrive/c/buildbot/worker/package_win64/build/src\rtutils.c:41 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:686 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:526 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:661 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:675 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:834 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_datatype at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:310 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:605 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:357 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:345 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_save_incremental at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:2289 jl_write_compiler_output at /cygdrive/c/buildbot/worker/package_win64/build/src\precompile.c:65 jl_atexit_hook at /cygdrive/c/buildbot/worker/package_win64/build/src\init.c:211 jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:702 mainCRTStartup at /cygdrive/c/buildbot/worker/package_win64/build/cli\loader_exe.c:42 BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line) RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line) ``` The precompilation from SciML/OrdinaryDiffEq.jl#1627 seems to not work with opaque closures. Do they not support precompilation? @Keno
With SnoopPrecompile, using OrdinaryDiffEq
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem{true,false}(f, u0, tspan, Float64[])
function lorenz(du, u, p, t)
du[1] = 10.0(u[2] - u[1])
du[2] = u[1] * (28.0 - u[3]) - u[2]
du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
typeof(prob) === typeof(lorenzprob) # true
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.871556 seconds (508.96 k allocations: 29.197 MiB, 99.70% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23(chunk_size=1))
# 0.766246 seconds (70.68 k allocations: 2.929 MiB, 99.65% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.000144 seconds (950 allocations: 45.547 KiB)
@time sol = solve(lorenzprob, Rosenbrock23(chunk_size=1))
# 0.000138 seconds (673 allocations: 68.594 KiB)
lorenzprob2 = ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 8.901039 seconds (26.31 M allocations: 3.869 GiB, 5.77% gc time, 99.98% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23(chunk_size=1))
# 2.060342 seconds (6.37 M allocations: 542.085 MiB, 3.91% gc time, 99.85% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 0.000122 seconds (950 allocations: 45.188 KiB)
@time sol = solve(lorenzprob2, Rosenbrock23(chunk_size=1))
# 0.000122 seconds (673 allocations: 67.812 KiB) |
using OrdinaryDiffEq, SnoopCompile
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem{true,false}(f, u0, tspan, Float64[])
function lorenz(du, u, p, t)
du[1] = 10.0(u[2] - u[1])
du[2] = u[1] * (28.0 - u[3]) - u[2]
du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
typeof(prob) === typeof(lorenzprob) # true
tadch1 = @snoopi_deep solve(prob, Rosenbrock23(chunk_size=1));
julia> accumulate_by_source(flatten(tadch1))
6-element Vector{Tuple{Float64, Union{Method, Core.MethodInstance}}}:
(7.75e-5, Vector{T}(::UndefInitializer, d::Tuple{Int64}) where T in Core at boot.jl:468)
(8.88e-5, (Array{T})(::UndefInitializer, d::Tuple{Vararg{Int64, N}}) where {T, N} in Core at boot.jl:476)
(0.0001195, Vector{T}(::UndefInitializer, m::Int64) where T in Core at boot.jl:459)
(0.0001459, NamedTuple{names, T}(args::T) where {names, T<:Tuple} in Core at boot.jl:607)
(0.0002753, (NamedTuple{names})(args::Tuple) where names in Core at boot.jl:603)
(1.0345707, ROOT() in Core.Compiler.Timings at compiler/typeinfer.jl:77) |
This is a continuation of #736 instead using OpaqueClosures. As such, it also requires: - SciML/SciMLBase.jl#143 - SciML/OrdinaryDiffEq.jl#1627 But now the MWE doesn't run: ```julia using OrdinaryDiffEq function f(du, u, p, t) du[1] = 0.2u[1] du[2] = 0.4u[2] end u0 = ones(2) tspan = (0.0, 1.0) prob = ODEProblem{true,false}(f, u0, tspan, Float64[]) function lorenz(du, u, p, t) du[1] = 10.0(u[2] - u[1]) du[2] = u[1] * (28.0 - u[3]) - u[2] du[3] = u[1] * u[2] - (8 / 3) * u[3] end lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) typeof(prob) === typeof(lorenzprob) # true @time sol = solve(prob, Rosenbrock23(autodiff=false)) @time sol = solve(prob, Rosenbrock23(chunk_size=1)) ``` ```julia [ Info: Precompiling OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] fatal: error thrown and no exception handler available. ErrorException("unimplemented: serialization of MethodInstances for OpaqueClosure") jl_error at /cygdrive/c/buildbot/worker/package_win64/build/src\rtutils.c:41 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:686 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:526 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:661 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:675 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:870 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:834 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_datatype at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:310 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:605 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:357 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_module at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:345 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:733 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:565 jl_serialize_value_ at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:510 [inlined] jl_save_incremental at /cygdrive/c/buildbot/worker/package_win64/build/src\dump.c:2289 jl_write_compiler_output at /cygdrive/c/buildbot/worker/package_win64/build/src\precompile.c:65 jl_atexit_hook at /cygdrive/c/buildbot/worker/package_win64/build/src\init.c:211 jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:702 mainCRTStartup at /cygdrive/c/buildbot/worker/package_win64/build/cli\loader_exe.c:42 BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line) RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line) ``` The precompilation from SciML/OrdinaryDiffEq.jl#1627 seems to not work with opaque closures. Do they not support precompilation? @Keno
Needs: - SciML/SciMLBase.jl#143 - SciML/OrdinaryDiffEq.jl#1627 ```julia using OrdinaryDiffEq function f(du, u, p, t) du[1] = 0.2u[1] du[2] = 0.4u[2] end u0 = ones(2) tspan = (0.0, 1.0) prob = ODEProblem{true,false}(f, u0, tspan, Float64[]) function lorenz(du, u, p, t) du[1] = 10.0(u[2] - u[1]) du[2] = u[1] * (28.0 - u[3]) - u[2] du[3] = u[1] * u[2] - (8 / 3) * u[3] end lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) typeof(prob) === typeof(lorenzprob) # true @time sol = solve(prob, Rosenbrock23(autodiff=false)) @time sol = solve(prob, Rosenbrock23(chunk_size=1)) ``` ``` 2.763588 seconds (10.32 M allocations: 648.718 MiB, 4.92% gc time, 99.89% compilation time) 10.577789 seconds (45.44 M allocations: 2.760 GiB, 4.87% gc time, 99.97% compilation time) ``` While the types of `prob` are exactly the same, there is still a significant amount of compile time, even with that exact same time being called in `using` at OrdinaryDiffEq. Maybe this needs to be run on master?
c0e7570
to
c91f55d
Compare
Without a system image: using OrdinaryDiffEq
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem{true,false}(f, u0, tspan, Float64[])
function lorenz(du, u, p, t)
du[1] = 10.0(u[2] - u[1])
du[2] = u[1] * (28.0 - u[3]) - u[2]
du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
typeof(prob) === typeof(lorenzprob) # true
@time sol = solve(lorenzprob, Rosenbrock23())
# 0.847580 seconds (83.25 k allocations: 3.404 MiB, 99.75% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.701598 seconds (499.23 k allocations: 28.846 MiB, 99.73% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23())
# 0.000113 seconds (457 allocations: 39.828 KiB)
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.000147 seconds (950 allocations: 45.547 KiB)
lorenzprob2 = ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
@time sol = solve(lorenzprob2, Rosenbrock23())
# 8.587653 seconds (24.77 M allocations: 3.581 GiB, 5.37% gc time, 99.99% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 1.122847 seconds (3.69 M allocations: 211.491 MiB, 2.45% gc time, 99.98% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23())
# 0.000120 seconds (455 allocations: 39.531 KiB)
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 0.000138 seconds (950 allocations: 45.188 KiB) With a system image: using PackageCompiler
create_sysimage(["OrdinaryDiffEq"], sysimage_path="DiffEqSysImage.so")
using OrdinaryDiffEq
function f(du, u, p, t)
du[1] = 0.2u[1]
du[2] = 0.4u[2]
end
u0 = ones(2)
tspan = (0.0, 1.0)
prob = ODEProblem{true,false}(f, u0, tspan, Float64[])
function lorenz(du, u, p, t)
du[1] = 10.0(u[2] - u[1])
du[2] = u[1] * (28.0 - u[3]) - u[2]
du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
lorenzprob = ODEProblem{true,false}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
typeof(prob) === typeof(lorenzprob) # true
@time sol = solve(lorenzprob, Rosenbrock23())
# 0.133316 seconds (4.66 k allocations: 309.428 KiB, 2.40% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.097989 seconds (432.99 k allocations: 26.587 MiB, 99.01% compilation time)
@time sol = solve(lorenzprob, Rosenbrock23())
# 0.000105 seconds (457 allocations: 39.828 KiB)
@time sol = solve(lorenzprob, Rosenbrock23(autodiff=false))
# 0.000138 seconds (950 allocations: 45.547 KiB)
lorenzprob2 = ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[])
@time sol = solve(lorenzprob2, Rosenbrock23())
# 7.651692 seconds (23.73 M allocations: 3.516 GiB, 8.12% gc time, 99.99% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 1.120606 seconds (2.67 M allocations: 145.677 MiB, 27.06% gc time, 99.98% compilation time)
@time sol = solve(lorenzprob2, Rosenbrock23())
# 0.000098 seconds (455 allocations: 39.531 KiB)
@time sol = solve(lorenzprob2, Rosenbrock23(autodiff=false))
# 0.000140 seconds (950 allocations: 45.188 KiB) |
Needs:
While the types of
prob
are exactly the same, there is still a significant amount of compile time, even with that exact same time being called inusing
at OrdinaryDiffEq.Maybe this needs to be run on master?