I am trying to run several different JuMP models at once in parallel and I have a MWE, and was curious if anyone has any suggestions or thoughts on what I am doing. A serial approach (where only a single type of model is run) would look like:
# serial approach
using JuMP, Ipopt
m = Model()
setsolver(m,Ipopt.IpoptSolver(print_level=0))
@variable(m, x, start = 0.0)
@variable(m, y, start = 0.0)
c = @constraint(m, x + y == 10)
@NLobjective(m, Min, (1-x)^2 + 90(y-x^2)^2)
s = solve(m)
runNum = 10
tp = zeros(runNum)
for R in 1:runNum
# update parameters
r = rand(1)[1]
tic()
m = Model()
setsolver(m,Ipopt.IpoptSolver(print_level=0))
@variable(m, x, start = 0.0)
@variable(m, y, start = 0.0)
c = @constraint(m, x + y == 10)
@NLobjective(m, Min, (1-x)^2 + 90(y-x^2)^2)
s = solve(m)
tp[R]=toc()
end
Then to run different models in parallel, I defined par.jl
as:
using JuMP, Ipopt
type Info
mdl
status
ch
end
# fucntion to initialize the model
function init(obj)
print("In init() with proc: ",myid(),"\n")
m = Model()
setsolver(m,Ipopt.IpoptSolver(print_level=0))
@variable(m, x, start = 0.0)
@variable(m, y, start = 0.0)
c = @constraint(m, x + y == 10)
if obj == :A
@NLobjective(m, Min, (1-x)^2 + 90(y-x^2)^2)
else
@NLobjective(m, Min, (1-x)^2 + 100(y-x^2)^2)
end
s = solve(m)
I = Info(m,s,c)
return I
end
# function to rerun optimization with new parameter
function update(I,r)
print("\n In update() with proc: ",myid(),"\n")
JuMP.setRHS(I.ch,rand(1)[1])
status = solve(I.mdl)
return status
end
Then to run the parallel approach I first fire up julia with julia -p 4
and run the script:
@everywhere include("par.jl")
m1 = @spawn init(:A)
m2 = @spawn init(:B)
m3 = @spawn init(:C)
m4 = @spawn init(:D)
runNum = 10
tp = zeros(runNum)
for R in 1:runNum
# update parameters
r = rand(1)[1]
tic()
u1 = @spawn update(fetch(m1),r) # doing fetch inside function call is OK
u2 = @spawn update(fetch(m2),r)
u3 = @spawn update(fetch(m3),r)
u4 = @spawn update(fetch(m4),r)
r1 = fetch(u1)
r2 = fetch(u2)
r3 = fetch(u3)
r4 = fetch(u4)
tp[R] = toc()
end
Comparing the results for all runs, it can be seen that even though (I thought that the init()
function already performed a solve()
the first run is very high. Any ideas why? I am passing data properly? Should I be doing something differently? If not I do not mind this, I just cannot explain it.
Then, cutting off the first run so that the final ones can be seen
As I would expect even though we are running multiple jobs, since they are in parallel they run faster.
So, what I am wondering from this:
- is there anything that I can do to improve this?
- Should I set this up as a cluster even though I do not need a complicated scheme as my nodes do not share information
- Assuming that I do not need to formally set up a cluster, in terms of managing these nodes, I would just be interested in if an
:Optimal
solution was obtained and if more than one have an:Optimal
solution what is the best:cost
. Then I would use data from that node for somthing else
Thanks