Skip to content

Long compilation time some numbers + included examples #1461

@JKRT

Description

@JKRT

Hi,

I would like to start by apologizing for a long text...

I have the following models, note these models are automatically generated based on different parameters to the following Modelica model

model Casc
  parameter Integer N = 10 "Order of the system"; // This parameter can be changed to increase the number of equations
  final parameter Real tau = T/N "Individual time constant";
  parameter Real T = 1 "System delay";
  Real x[N] (each start = 0, each fixed = true);
equation
  tau*der(x[1]) = 1 - x[1];
  for i in 2:N loop
    tau*der(x[i]) = x[i-1] - x[i];
  end for;
end Casc;

The corresponding MTK model for N = 10 (Take note that this code is automatically generated) is:

    using ModelingToolkit
    using DifferentialEquations
    begin
        begin
            saved_values_Casc10 = SavedValues(Float64, Tuple{Float64,Array})
            function Casc10CallbackSet(aux)
                local p = aux[1]
                local reals = aux[2]
                nothing
                return CallbackSet()
            end
        end
        function Casc10Model(tspan = (0.0, 1.0))
            @variables t            #= C:\Users\johti17\Projects\Programming\JuliaPackages\OM.jl\OMBackend.jl\src\CodeGeneration\MTK_CodeGeneration.jl:219 =#
            parameters = ModelingToolkit.@parameters((N, tau, T)) #= C:\Users\johti17\Projects\Programming\JuliaPackages\OM.jl\OMBackend.jl\src\CodeGeneration\MTK_CodeGeneration.jl:220 =#
            vars = ModelingToolkit.@variables((
                x_1(t),
                x_2(t),
                x_3(t),
                x_4(t),
                x_5(t),
                x_6(t),
                x_7(t),
                x_8(t),
                x_9(t),
                x_10(t),
            )) #= C:\Users\johti17\Projects\Programming\JuliaPackages\OM.jl\OMBackend.jl\src\CodeGeneration\MTK_CodeGeneration.jl:227 =#
            der = Differential(t)
            eqs = [
                der(x_1) ~ (1.0 - x_1) / tau,
                der(x_2) ~ (x_1 - x_2) / tau,
                der(x_3) ~ (x_2 - x_3) / tau,
                der(x_4) ~ (x_3 - x_4) / tau,
                der(x_5) ~ (x_4 - x_5) / tau,
                der(x_6) ~ (x_5 - x_6) / tau,
                der(x_7) ~ (x_6 - x_7) / tau,
                der(x_8) ~ (x_7 - x_8) / tau,
                der(x_9) ~ (x_8 - x_9) / tau,
                der(x_10) ~ (x_9 - x_10) / tau,
            ]
            nonLinearSystem = ModelingToolkit.ODESystem(
                eqs,
                t,
                vars,
                parameters,
                name = :($(Symbol("Casc10"))),
            )
            nonLinearSystem = ModelingToolkit.structural_simplify(nonLinearSystem)
            pars = Dict(N => float(10), tau => float(T / 10.0), T => float(1.0))
            initialValues = [
                x_1 => 0.0,
                x_2 => 0.0,
                x_3 => 0.0,
                x_4 => 0.0,
                x_5 => 0.0,
                x_6 => 0.0,
                x_7 => 0.0,
                x_8 => 0.0,
                x_9 => 0.0,
                x_10 => 0.0,
            ]
            firstOrderSystem = ModelingToolkit.ode_order_lowering(nonLinearSystem)
            reducedSystem = firstOrderSystem
            local event_p = [10, 0, 1.0]
            local discreteVars = collect(values(Dict([])))
            local event_vars = vcat(
                collect(
                    values(
                        Dict([
                            x_1 => 0.0,
                            x_2 => 0.0,
                            x_3 => 0.0,
                            x_4 => 0.0,
                            x_5 => 0.0,
                            x_6 => 0.0,
                            x_7 => 0.0,
                            x_8 => 0.0,
                            x_9 => 0.0,
                            x_10 => 0.0,
                        ]),
                    ),
                ),
                discreteVars,
            )
            local aux = Array{Array{Float64}}(undef, 2)
            aux[1] = event_p
            aux[2] = event_vars
            problem = ModelingToolkit.ODEProblem(
                reducedSystem,
                initialValues,
                tspan,
                pars,
                callback = Casc10CallbackSet(aux),
                cse = true,
            )
            return (problem, initialValues, reducedSystem, tspan, pars, vars)
        end
    end
    (Casc10Model_problem, _, _, _, _, _) = Casc10Model()
    function Casc10Simulate(tspan)
        return solve(Casc10Model_problem, tspan = tspan)
    end
    function Casc10Simulate(tspan = (0.0, 1.0); solver = Rodas5())
        return solve(Casc10Model_problem, tspan = tspan, solver)
    end

A sample current timings (On my laptop) MTK compilation + Simulation

10:
  0.305501 seconds (477.56 k allocations: 27.560 MiB, 90.20% compilation time)
100:
  1.420337 seconds (1.56 M allocations: 80.551 MiB, 93.48% compilation time)

200: 
  3.867602 seconds (2.81 M allocations: 147.689 MiB, 93.44% compilation time)

400: (Up a lot from 200, memory is linear though)
 26.180517 seconds (5.33 M allocations: 305.115 MiB, 1.05% gc time, 97.28% compilation time)

800:
 99.175782 seconds (10.28 M allocations: 708.155 MiB, 0.21% gc time, 95.19% compilation time)

Sorry for a long post, I suppose a related issue is #1286 and #1285

Models are attached for reference. I uploaded them as txt files since the GitHub issue API do not seem to support .jl files
Casc10.txt
Casc100.txt
Casc200.txt
Casc400.txt
Casc800.txt
Casc1600.txt

It also takes quite some time just including the models, say that I have a model like the ones attached, how could I decompose the system better in order to reduce the compilation time overhead?

I suppose splitting the declarations of variables into separate functions might do something?
See JuliaLang/julia#19158

But then the question is how could I go about splitting the declaration of variables and equations to built it up in parts?

Say that I want to register 100 variables at the time using @variables

(Feel free to rework these Julia models so that they look more idiomatic and use them for benchmarking)

Cheers,
John 🚀

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions