@@ -33,7 +33,7 @@ rn = complete(prnbng.rn; split = false)
3333obs = [eq.lhs for eq in observed(rn)]
3434osys = convert(ODESystem, rn)
3535
36- rhs = [eq.rhs for eq in full_equations(osys)]
36+ rhs = [eq.rhs for eq in full_equations(osys)][1:10]
3737vars = unknowns(osys)
3838pars = parameters(osys)
3939
@@ -55,10 +55,13 @@ args = (vars, pars, ModelingToolkit.get_iv(osys))
5555# out of place versions run into an error saying the expression is too large
5656# due to the `SymbolicUtils.Code.create_array` call. `iip_config` prevents it
5757# from trying to build the function.
58- kwargs = (; iip_config = (false, true), expression = Val{false })
58+ kwargs = (; iip_config = (false, true), expression = Val{true })
5959@timeit to "Build jacobian - no CSE" _, jac_nocse_iip = build_function(jac, args...; cse = false, kwargs...);
6060@timeit to "Build jacobian - CSE" _, jac_cse_iip = build_function(jac, args...; cse = true, kwargs...);
6161
62+ jac_nocse_iip = eval(jac_nocse_iip)
63+ jac_cse_iip = eval(jac_cse_iip)
64+
6265defs = defaults(osys)
6366u = Float64[Symbolics.fixpoint_sub(var, defs) for var in vars]
6467buffer_cse = similar(jac, Float64)
@@ -81,7 +84,7 @@ We'll also measure scaling.
8184
8285
8386```julia
84- function run_and_time !(rhs, vars, pars, iv, u0, p, t0, N, i, jac_times, jac_allocs, build_times, first_call_times, second_call_times )
87+ function run_and_time_construct !(rhs, vars, pars, iv, N, i, jac_times, jac_allocs, build_times, functions )
8588 outputs = rhs[1:N]
8689 SymbolicUtils.ENABLE_HASHCONSING[] = false
8790 jac_result = @be Symbolics.sparsejacobian(outputs, vars)
@@ -99,46 +102,70 @@ function run_and_time!(rhs, vars, pars, iv, u0, p, t0, N, i, jac_times, jac_allo
99102 @assert isequal(jac_nohc, jac_hc)
100103 jac = jac_hc
101104 args = (vars, pars, iv)
102- kwargs = (; iip_config = (false, true), expression = Val{false })
105+ kwargs = (; iip_config = (false, true), expression = Val{true })
103106
104107 build_result = @be build_function(jac, args...; cse = false, kwargs...);
105108 build_times[1][i] = minimum(x -> x.time, build_result.samples)
106- jacfn_nocse = build_function(jac, args...; cse = false, kwargs...)[2]
109+ jacfn_nocse = eval( build_function(jac, args...; cse = false, kwargs...)[2])
107110
108111 build_result = @be build_function(jac, args...; cse = true, kwargs...);
109112 build_times[2][i] = minimum(x -> x.time, build_result.samples)
110- jacfn_cse = build_function(jac, args...; cse = true, kwargs...)[2]
113+ jacfn_cse = eval(build_function(jac, args...; cse = true, kwargs...)[2])
114+
115+ functions[1][i] = let buffer = similar(jac, Float64), fn = jacfn_nocse
116+ function nocse(u, p, t)
117+ fn(buffer, u, p, t)
118+ buffer
119+ end
120+ end
121+ functions[2][i] = let buffer = similar(jac, Float64), fn = jacfn_cse
122+ function cse(u, p, t)
123+ fn(buffer, u, p, t)
124+ buffer
125+ end
126+ end
127+
128+ return nothing
129+ end
130+
131+ function run_and_time_call!(i, u, p, tt, functions, first_call_times, second_call_times)
132+ jacfn_nocse = functions[1][i]
133+ jacfn_cse = functions[2][i]
111134
112- buffer = similar(jac, Float64)
113- call_result = @timed jacfn_nocse(buffer, u0, p, t0)
135+ call_result = @timed jacfn_nocse(u, p, tt)
114136 first_call_times[1][i] = call_result.time
115- call_result = @timed jacfn_cse(buffer, u0, p, t0 )
137+ call_result = @timed jacfn_cse(u, p, tt )
116138 first_call_times[2][i] = call_result.time
117139
118- call_result = @be jacfn_nocse(buffer, u0, p, t0 )
140+ call_result = @be jacfn_nocse(u, p, tt )
119141 second_call_times[1][i] = minimum(x -> x.time, call_result.samples)
120- call_result = @be jacfn_cse(buffer, u0, p, t0 )
142+ call_result = @be jacfn_cse(u, p, tt )
121143 second_call_times[2][i] = minimum(x -> x.time, call_result.samples)
122-
123- return nothing
124144end
125145```
126146
127147# Run benchmark
128148
129149```julia
130- N = [10, 20, 40, 60, 100, 200, 300, 400 ]
150+ N = [10, 20, 40, 80 ]
131151jacobian_times = [zeros(Float64, length(N)), zeros(Float64, length(N))]
132152jacobian_allocs = copy.(jacobian_times)
153+ functions = [Vector{Any}(undef, length(N)), Vector{Any}(undef, length(N))]
133154# [without_cse_times, with_cse_times]
134155build_times = copy.(jacobian_times)
135156first_call_times = copy.(jacobian_times)
136157second_call_times = copy.(jacobian_times)
137158
138159iv = ModelingToolkit.get_iv(osys)
139- run_and_time!(rhs, vars, pars, iv, u, p, tt, 10, 1, jacobian_times, jacobian_allocs, build_times, first_call_times, second_call_times)
160+ run_and_time_construct!(rhs, vars, pars, iv, 10, 1, jacobian_times, jacobian_allocs, build_times, functions)
161+ run_and_time_call!(1, u, p, tt, functions, first_call_times, second_call_times)
162+ for (i, n) in enumerate(N)
163+ @info i n
164+ run_and_time_construct!(rhs, vars, pars, iv, n, i, jacobian_times, jacobian_allocs, build_times, functions)
165+ end
140166for (i, n) in enumerate(N)
141- run_and_time!(rhs, vars, pars, iv, u, p, tt, n, i, jacobian_times, jacobian_allocs, build_times, first_call_times, second_call_times)
167+ @info i n
168+ run_and_time_call!(i, u, p, tt, functions, first_call_times, second_call_times)
142169end
143170```
144171
0 commit comments