-
Notifications
You must be signed in to change notification settings - Fork 1
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
Support ScalarNonlinearFunction
#30
Conversation
It might also be nice to include a test with |
Benchmarks on pglib. This is the Rosetta-OPF implementation, with
Interestingly, the graph construction time here is slower than what I report here. Maybe I'm not parsing |
JuMP has released the nonlinear expression system, but this needs some profiling (as well as updated examples) before it can be merged. In particular, we see a 4x slowdown in incidence graph construction on the 20-30k bus pglib instances when using |
ScalarNonlinearFunction
ScalarNonlinearFunction
A large portion of the overhead appears to be in 1457 583 @MathProgIncidence/src/identify_variables.jl 228 identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
1625 32 @MathProgIncidence/src/identify_variables.jl 155 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
1706 2 @MathProgIncidence/src/identify_variables.jl 132 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
1846 0 @MathProgIncidence/src/incidence_graph.jl 138 #get_bipartite_incidence_graph#14
2000 0 @MathProgIncidence/src/incidence_graph.jl 122 get_bipartite_incidence_graph
2039 0 @MathProgIncidence/src/interface.jl 134 MathProgIncidence.IncidenceGraphInterface(m::JuMP.Model)
2039 0 @MathProgIncidence/src/interface.jl 134 #IncidenceGraphInterface#61
2041 0 @Base/client.jl 522 _start()
2041 0 @Base/client.jl 307 exec_options(opts::Base.JLOptions)
2041 0 @Base/Base.jl 457 include(mod::Module, _path::String)
2041 0 @Base/loading.jl 1963 _include(mapexpr::Function, mod::Module, _path::String)
2041 0 @Base/loading.jl 1903 include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
2041 2 @Base/boot.jl 370 eval It's a little difficult to tell exactly what is taking the most time within this function: 12╎ ╎ ╎ 825 @MathProgIncidence/src/identify_variables.jl:155; identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{Mat...
87╎ ╎ ╎ 726 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
73╎ ╎ ╎ 592 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
100╎ ╎ ╎ ╎ 438 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
47╎ ╎ ╎ ╎ 192 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
╎ ╎ ╎ ╎ 74 @MathProgIncidence/src/identify_variables.jl:246; identify_unique_variables(fcn::MathOptInterface.ScalarAffineFunction{Float64})
╎ ╎ ╎ ╎ 68 @MathProgIncidence/src/identify_variables.jl:246; identify_unique_variables(fcn::MathOptInterface.ScalarQuadraticFunction{Float64})
1╎ ╎ ╎ 58 @MathProgIncidence/src/identify_variables.jl:232; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction) 25╎ ╎ ╎ 824 @MathProgIncidence/src/identify_variables.jl:155; identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{Mat...
66╎ ╎ ╎ 745 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
85╎ ╎ ╎ 606 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
86╎ ╎ ╎ ╎ 405 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
40╎ ╎ ╎ ╎ 194 @MathProgIncidence/src/identify_variables.jl:228; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
╎ ╎ ╎ ╎ 75 @MathProgIncidence/src/identify_variables.jl:246; identify_unique_variables(fcn::MathOptInterface.ScalarQuadraticFunction{Float64})
╎ ╎ ╎ ╎ 59 @MathProgIncidence/src/identify_variables.jl:332; _filter_duplicates(indices::Vector{MathOptInterface.VariableIndex})
╎ ╎ ╎ ╎ 59 @Base/set.jl:45; Set
2╎ ╎ ╎ ╎ ╎ 59 @Base/dict.jl:70; Dict{MathOptInterface.VariableIndex, Nothing}()
╎ ╎ ╎ ╎ 50 @MathProgIncidence/src/identify_variables.jl:246; identify_unique_variables(fcn::MathOptInterface.ScalarQuadraticFunction{Float64})
╎ ╎ ╎ ╎ 72 @MathProgIncidence/src/identify_variables.jl:232; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
╎ ╎ ╎ ╎ 54 @MathProgIncidence/src/identify_variables.jl:332; _filter_duplicates(indices::Vector{MathOptInterface.VariableIndex})
╎ ╎ ╎ ╎ 54 @Base/set.jl:45; Set
2╎ ╎ ╎ ╎ 53 @Base/dict.jl:70; Dict{MathOptInterface.VariableIndex, Nothing}()
|
We can get rid of the 82 0 @Base/array.jl 1061 push!
83 0 @Base/array.jl 126 vect
83 0 @Base/array.jl 674 _array_for
89 0 @Base/array.jl 671 _array_for
89 0 @Base/abstractarray.jl 883 similar
89 0 @Base/abstractarray.jl 884 similar
92 0 @Base/array.jl 1061 push!(a::Vector{MathOptInterface.VariableIndex}, item::MathOptInterface.VariableIndex)
108 0 @MathProgIncidence/src/get_equality.jl 183 get_equality_constraints
108 0 @JuMP/src/constraints.jl 1422 all_constraints
108 16 @JuMP/src/constraints.jl 1429 all_constraints(model::JuMP.Model; include_variable_in_set_constraints::Bool)
118 0 @Base/boot.jl 486 Array
121 63 @MathProgIncidence/src/identify_variables.jl 239 _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
154 154 @MathProgIncidence/src/identify_variables.jl 240 _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
174 0 @MathProgIncidence/src/incidence_graph.jl 128 #get_bipartite_incidence_graph#14
174 0 @MathProgIncidence/src/get_equality.jl 313 _get_constraints
174 0 @MathProgIncidence/src/get_equality.jl 324 _get_constraints(model::JuMP.Model; include_inequality::Bool, include_active_inequalities::Bool, tolerance::Float64)
175 175 @Base/array.jl 1014 _growend!
217 217 @Base/boot.jl 477 Array
730 11 @MathProgIncidence/src/identify_variables.jl 79 identify_unique_variables(constraints::Vector{JuMP.ConstraintRef})
731 9 @MathProgIncidence/src/incidence_graph.jl 171 get_bipartite_incidence_graph(constraints::Vector{JuMP.ConstraintRef}, variables::Vector{JuMP.VariableRef})
746 0 @MathProgIncidence/src/incidence_graph.jl 144 get_bipartite_incidence_graph
804 0 @MathProgIncidence/src/incidence_graph.jl 147 get_bipartite_incidence_graph
1004 666 @MathProgIncidence/src/identify_variables.jl 238 _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
1138 2 @MathProgIncidence/src/identify_variables.jl 229 identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
1329 69 @MathProgIncidence/src/identify_variables.jl 158 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
1437 2 @MathProgIncidence/src/identify_variables.jl 135 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
1550 0 @MathProgIncidence/src/incidence_graph.jl 138 #get_bipartite_incidence_graph#14
1724 0 @MathProgIncidence/src/incidence_graph.jl 122 get_bipartite_incidence_graph
1750 0 @MathProgIncidence/src/interface.jl 134 MathProgIncidence.IncidenceGraphInterface(m::JuMP.Model)
1750 0 @MathProgIncidence/src/interface.jl 134 #IncidenceGraphInterface#61
1772 0 @Base/client.jl 522 _start()
1772 0 @Base/client.jl 307 exec_options(opts::Base.JLOptions)
1772 0 @Base/Base.jl 457 include(mod::Module, _path::String)
1772 0 @Base/loading.jl 1963 _include(mapexpr::Function, mod::Module, _path::String)
1772 0 @Base/loading.jl 1903 include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
1772 22 @Base/boot.jl 370 eval The comparison between the two approaches is now:
Breakdown of waht is happening inside of ╎ ╎ 1550 @MathProgIncidence/src/incidence_graph.jl:138; #get_bipartite_incidence_graph#14
╎ ╎ 746 @MathProgIncidence/src/incidence_graph.jl:144; get_bipartite_incidence_graph
11╎ ╎ ╎ 730 @MathProgIncidence/src/identify_variables.jl:79; identify_unique_variables(constraints::Vector{JuMP.ConstraintRef})
1╎ ╎ ╎ 713 @MathProgIncidence/src/identify_variables.jl:135; identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{Mat...
39╎ ╎ ╎ 675 @MathProgIncidence/src/identify_variables.jl:158; identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{Mat...
╎ ╎ ╎ 574 @MathProgIncidence/src/identify_variables.jl:229; identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
94╎ ╎ ╎ 480 @MathProgIncidence/src/identify_variables.jl:238; _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
87╎ ╎ ╎ ╎ 335 @MathProgIncidence/src/identify_variables.jl:238; _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
70╎ ╎ ╎ ╎ 194 @MathProgIncidence/src/identify_variables.jl:238; _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
37╎ ╎ ╎ ╎ 68 @MathProgIncidence/src/identify_variables.jl:238; _identify_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
╎ ╎ ╎ ╎ 28 @MathProgIncidence/src/identify_variables.jl:303; _identify_variables(var::Float64)
╎ ╎ ╎ ╎ 28 @MathProgIncidence/src/identify_variables.jl:251; _identify_variables(fcn::MathOptInterface.ScalarQuadraticFunction{Float64})
╎ ╎ ╎ ╎ 28 @MathProgIncidence/src/identify_variables.jl:361; _identify_variables
╎ ╎ ╎ ╎ 28 @Base/array.jl:126; vect
╎ ╎ ╎ ╎ 28 @Base/array.jl:674; _array_for
╎ ╎ ╎ ╎ ╎ 28 @Base/array.jl:671; _array_for
╎ ╎ ╎ ╎ ╎ 28 @Base/abstractarray.jl:883; similar
╎ ╎ ╎ ╎ ╎ 28 @Base/abstractarray.jl:884; similar
╎ ╎ ╎ ╎ ╎ 28 @Base/boot.jl:486; Array
28╎ ╎ ╎ ╎ ╎ 28 @Base/boot.jl:477; Array We probably need to be more efficient about recursively building up the array of variables (i.e. build it in-place instead of allocating new arrays all the time). |
Once we build up the variable array in-place, the comparison starts to look a lot better:
We can still see a good amount of overhead in the new 95 95 @Base/boot.jl 477 Array
146 0 @MathProgIncidence/src/incidence_graph.jl 128 #get_bipartite_incidence_graph#14
146 0 @MathProgIncidence/src/get_equality.jl 313 _get_constraints
146 0 @MathProgIncidence/src/get_equality.jl 324 _get_constraints(model::JuMP.Model; include_inequality::Bool, include_active_inequalities::Bool, tolerance::Float64)
244 11 @MathProgIncidence/src/incidence_graph.jl 171 get_bipartite_incidence_graph(constraints::Vector{JuMP.ConstraintRef}, variables::Vector{JuMP.VariableRef})
268 239 @MathProgIncidence/src/identify_variables.jl 246 _collect_variables!(variables::Vector{MathOptInterface.VariableIndex}, fcn::MathOptInterface.ScalarNonlinearFunction)
271 0 @MathProgIncidence/src/identify_variables.jl 237 _identify_variables
277 2 @MathProgIncidence/src/identify_variables.jl 79 identify_unique_variables(constraints::Vector{JuMP.ConstraintRef})
278 0 @MathProgIncidence/src/identify_variables.jl 229 identify_unique_variables(fcn::MathOptInterface.ScalarNonlinearFunction)
294 0 @MathProgIncidence/src/incidence_graph.jl 144 get_bipartite_incidence_graph
336 0 @MathProgIncidence/src/incidence_graph.jl 147 get_bipartite_incidence_graph
407 14 @MathProgIncidence/src/identify_variables.jl 158 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
508 1 @MathProgIncidence/src/identify_variables.jl 135 identify_unique_variables(constraint::JuMP.ConstraintRef{JuMP.Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadrat...
630 0 @MathProgIncidence/src/incidence_graph.jl 138 #get_bipartite_incidence_graph#14
776 0 @MathProgIncidence/src/incidence_graph.jl 122 get_bipartite_incidence_graph
798 0 @MathProgIncidence/src/interface.jl 134 MathProgIncidence.IncidenceGraphInterface(m::JuMP.Model)
798 0 @MathProgIncidence/src/interface.jl 134 #IncidenceGraphInterface#61
825 0 @Base/client.jl 522 _start()
825 0 @Base/client.jl 307 exec_options(opts::Base.JLOptions)
825 0 @Base/Base.jl 457 include(mod::Module, _path::String)
825 0 @Base/loading.jl 1963 _include(mapexpr::Function, mod::Module, _path::String)
825 0 @Base/loading.jl 1903 include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
825 27 @Base/boot.jl 370 eval
Total snapshots: 1195. Utilization: 100% across all threads and tasks. Use the `groupby` kwarg to break down by thread and/or task. We now have a ~50% performance hit in incidence graph construction when using ScalarNonlinearFunction. I think this makes sense, because we now have to construct the flattened data structure ourselves, instead of it already being constructed in
With |
ScalarNonlinearFunction
ScalarNonlinearFunction
This PR still needs:
Updates to examples/readmeSince the README is always public, and the documentation is for the current main branch, I'll defer these until a release, as I don't want the docs to diverge from the latest release.Possibly documentation thatMarking as complete asidentify_unique_variables
supportsFloat64
(to handle arbitrary nodes inScalarNonlinearFunction
)identify_unique_variables
no longer has to supportFloat64