Add example of building & solving JuMP models in parallel#4150
Add example of building & solving JuMP models in parallel#4150WalterMadelim wants to merge 1 commit intojump-dev:masterfrom
Conversation
Maybe this can be adapted to a more general form. I just share my code as a proposal.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4150 +/- ##
=======================================
Coverage 99.91% 99.91%
=======================================
Files 42 42
Lines 6224 6224
=======================================
Hits 6219 6219
Misses 5 5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Have you seen the examples lower down? https://jump.dev/JuMP.jl/dev/tutorials/algorithms/parallelism/#Example:-parameter-search-with-multi-threading |
|
I looked at it. I surmise that example is weak in terms of practical performance. It's probably not efficient to parallelize tasks where task1 is building and solving model and task2 is building and solving model. This style is probably easier to code. But I suspect that at runtime, the multithreading execution will degrade highly, e.g. when you observe htop, you may find that for the most of the time there is only a single core running. A better way should separate JuMP's modeling part and Gurobi's solving part entirely, since the nature of their jobs are different (JuMP allocates a lot, whereas MIP solving is computation heavy). |
|
How about this: using JuMP
import HiGHS
function build_model(s::Int; N::Int = 80)
model = Model(HiGHS.Optimizer)
set_silent(model)
@variable(model, x[1:N], Bin)
@variable(model, y[1:N], Bin)
@variable(model, z[1:N, 1:N] >= 0)
@constraint(model, [i in 1:N, j in 1:N], z[i, j] <= x[i])
@constraint(model, [i in 1:N, j in 1:N], z[i, j] <= y[j])
@constraint(model, [i in 1:N, j in 1:N], z[i, j] >= x[i] + y[j] - 1)
@objective(model, Min, sum(rand(-10:10) * i for i in z))
set_time_limit_sec(model, s)
return model
end
struct Solution
scenario::Int
objective_value::Float64
end
function solve_model(ch::Channel{Solution}, s::Int, model::Model)
optimize!(model)
@assert has_values(model) # There is always the trivial solution
put!(ch, Solution(s, objective_value(model)))
return
end
function run_example(S::Int)
models = Vector{Model}(undef, S)
Threads.@threads for s in 1:S
models[s] = build_model(s)
end
ch = Channel{Solution}()
for (s, model) in enumerate(models)
Threads.@spawn solve_model(ch, s, model)
end
for i in 1:S
solution = take!(ch)
println("s=$(solution) [solved $i/$S]")
end
return
end
run_example(15) |
:+100: This shouldn't be understated.
Why? |
|
How's #4155 |
Maybe this can be adapted to a more general form. I just share my code as a proposal.