OMJulia.jl
OMJulia.jl copied to clipboard
Multi-threading with OMJulia
Hi there! I am using OMJulia in VSCode and am trying to optimise the parameters of dynamic Modelica models.
I was wondering if the multi-threading of simulations is possible with OMJulia? I have tried creating multiple OMCSession objects and running parallel simulations across them but I get a "TaskFailedException" as soon as multiple simulations try to run at once. I am quite new to both OMJulia and multi-threading so I'm not sure if this is a limitation of OMJulia or a mistake on my end.
@JKRT can you please comment on that?
Hi there! I am using OMJulia in VSCode and am trying to optimise the parameters of dynamic Modelica models.
I was wondering if the multi-threading of simulations is possible with OMJulia? I have tried creating multiple OMCSession objects and running parallel simulations across them but I get a "TaskFailedException" as soon as multiple simulations try to run at once. I am quite new to both OMJulia and multi-threading so I'm not sure if this is a limitation of OMJulia or a mistake on my end.
Hello @Wardi0 thanks for raising the issue, could you provide a minimal example showcasing the issue, in principle, I believe it should work
Hi JKRT, thank you for helping with this issue! This is my code:
# Create an OMCSession for each thread, add to a vector and load the model on each
sessions = []
for thread in 1:Threads.nthreads()
push!(sessions, OMJulia.OMCSession())
sessions[thread].ModelicaSystem("package.mo","FusionPhD.ModelicaFluidModels.RankineCycles.SimpleCycleESSDemo2")
end
# Define the valid domain of the decision variables [gain, time constant]
upper = x -> [2000e-5,300.0]
lower = x -> [1e-5,1.0]
domain = Fresa.Domain(lower,upper)
# Objective function (minimise deviation integral)
function controller_error(x, sessions)
thread_id = Threads.threadid()
dev = Inf64 # Worst-case objective value
feasibility = 1.0 # Assume infeasible
try
sessions[thread_id].setParameters(["power_PI.k=$(x[1])", "power_PI.T=$(x[2])"]) # Set design parameters
println("Starting simulation on thread "*string(Int(thread_id)))
sessions[thread_id].simulate() # Simulate model with design parameters
dev = sessions[thread_id].getSolutions("controller_error")[1][end] # Extract objective value from simulation results
feasibility = 0.0 # Assume feasible if simulation runs with no errors
println("Simulation on thread "*string(Int(thread_id))*"\nObjective="*string(dev)*" | Feasibility="*string(feasibility))
catch TaskFailedException
println("Caught TaskFailedException on thread "*string(Int(thread_id)))
return (dev, feasibility)
end
return (dev, feasibility)
end
p0 = [Fresa.createpoint([350e-5,50.0], controller_error, sessions)] # Initial solution population
best, pop = Fresa.solve(controller_error, p0, domain; parameters=sessions, multithreading = true, ngen = 5) # Run Fresa optimiser
Based on my print statements, OMJulia is indeed running in parallel. It is just that the multi-threading raises these TaskFailedExceptions (seemingly at random to me); all the simulations ran fine with no errors on a single thread.
Perhaps you need to set a unique working directory for each OMCSession otherwise simulation will not work since it tries to delete and create files at the same location.
@adeas31 OMJulia creates a new temp directory for each OMCSession() by default and the simulations are done in separate working directory
Hi JKRT, thank you for helping with this issue! This is my code:
# Create an OMCSession for each thread, add to a vector and load the model on each sessions = [] for thread in 1:Threads.nthreads() push!(sessions, OMJulia.OMCSession()) sessions[thread].ModelicaSystem("package.mo","FusionPhD.ModelicaFluidModels.RankineCycles.SimpleCycleESSDemo2") end # Define the valid domain of the decision variables [gain, time constant] upper = x -> [2000e-5,300.0] lower = x -> [1e-5,1.0] domain = Fresa.Domain(lower,upper) # Objective function (minimise deviation integral) function controller_error(x, sessions) thread_id = Threads.threadid() dev = Inf64 # Worst-case objective value feasibility = 1.0 # Assume infeasible try sessions[thread_id].setParameters(["power_PI.k=$(x[1])", "power_PI.T=$(x[2])"]) # Set design parameters println("Starting simulation on thread "*string(Int(thread_id))) sessions[thread_id].simulate() # Simulate model with design parameters dev = sessions[thread_id].getSolutions("controller_error")[1][end] # Extract objective value from simulation results feasibility = 0.0 # Assume feasible if simulation runs with no errors println("Simulation on thread "*string(Int(thread_id))*"\nObjective="*string(dev)*" | Feasibility="*string(feasibility)) catch TaskFailedException println("Caught TaskFailedException on thread "*string(Int(thread_id))) return (dev, feasibility) end return (dev, feasibility) end p0 = [Fresa.createpoint([350e-5,50.0], controller_error, sessions)] # Initial solution population best, pop = Fresa.solve(controller_error, p0, domain; parameters=sessions, multithreading = true, ngen = 5) # Run Fresa optimiserBased on my print statements, OMJulia is indeed running in parallel. It is just that the multi-threading raises these TaskFailedExceptions (seemingly at random to me); all the simulations ran fine with no errors on a single thread.
@Wardi0 What version of OMJulia, and what platform are you on? Furthermore, would it be possible to get model, or if that is not possible that you try the same example with some other model that can be shared?
@JKRT Ah, I was not up-to-date. I was using OMJulia v0.1.0 on VSCode for Windows 10. I have created a repository with the code that produced the errors in that version if you are still interested (https://github.com/Wardi0/OMJulia_multithreading)
Having updated to OMJulia v0.2.1 though, I can no longer start an OMCSession. OMJulia seems to have made 2 files in the current directory, stderr.log and stdout.log, that I cannot edit without admin priveleges (university laptop with admin restrictions....), so trying to create an OMCSession throws:
IOError: open("stderr.log", 769, 420): permission denied (EACCES)
Is there any way around this?
@Wardi0 start your julia repl as administrator and it should work
@arun3688 My university does not give us admin rights on laptops :(
@Wardi0 One workaround to try what Arun suggested is to create a virtual machine and install everything you need in that image; in that way, you can be administrator. Still, of course, there are performance penalties if you do, but at least it can help to pinpoint the issue
Hi @JKRT, just wanted to update this thread. I am now using a Linux machine and have got multi-threading working with OMJulia so I think this issue can be closed.
I still cannot run it on Windows due to the IOError: open("stderr.log", 769, 420): permission denied (EACCES) error I mentioned above; my department's system admin was able to reproduce the error even with administrator priveleges. I can create a new issue for this though.
As an aside, is there a way to suppress the printed terminal output from OMJulia.OMCSession() and OMJulia.simulate? With multiple threads, the simulation output from OpenModelica makes the results quite hard to parse.