Continue a loop in Julia when the time out

When I use the DifferentialEquations.jl to solve a ODEs, some parameters set is time-consuming. I have write a loop to solve the ODEs at diverse parameters. I want to early terminate the time-consuming parameters set, for example more than 60 seconds and execute the next loop.

I don’t know how to realize this functions. Is there any the useful package? :grinning:

eventlet package in Python is seems to work, but I know few about python. I want to know if any similar package in Julia. :grinning:

2 Likes

Simplest solution maght be to use the maxiters flag in solve(... ;maxiters=1000, ...). If you realy need a more more accurate timing you can use a callback function:

using DiffEqBase, OrdinaryDiffEq

u0 = [1.,0.]
function fun(du,u,p,t)
   du[2] = -u[1]
   du[1] = u[2]
   sleep(0.1)  # throttle the function
end
tspan = (0.0,10.0)
prob = ODEProblem(fun,u0,tspan)


struct Timer
    tstart::Array{Float64,1}
    runtime::Float64
    Timer(t) = new([0.0],t)

end

function (timer::Timer)(u,t,integrator) 
    if timer.tstart[1] == 0.0 
                timer.tstart[1] = time()
    end
    time() - timer.tstart[1] >= timer.runtime && return true
end

affect!(integrator) = terminate!(integrator)
cb = DiscreteCallback(Timer(60),affect!)
sol = solve(prob,Tsit5(),callback=cb)

Thanks a lot :grinning:
I found the diverse parameters often get different iteration times.
Besides, I found some parameter combinations really cause the solver too slow - it showed me Interrupted. Larger maxiters is needed. after a few hours, when i use the default maxiters flag. It also occupy too many memory. While, some parameter combinations may show me the solution a few seconds later. (both I used the AutoTsit5(Rosenbrock23()) solver).

I have noticed Base.Threads.@spawn could created a task of solve(...), and run in “backstage”. Then I can use timedwait(() -> istaskdone(tsk1), max_runtime) to timer the task. but I don’t know how to kill the task. Could you give me some advices? :face_with_monocle:

using DifferentialEquations
u0 = [1.,0.]
function fun(du,u,p,t)
   du[2] = -u[1]
   du[1] = u[2]
   sleep(0.1)  # throttle the function
end
tspan = (0.0,10.0)
prob = ODEProblem(fun,u0,tspan)

max_runtime = 10.0
tsk1 = Base.Threads.@spawn solve(prob, Tsit5())
timedwait(() -> istaskdone(tsk1), max_runtime)
if istaskdone(tsk1)
    sol = fetch(tsk1)
else 
    interrupt() # I don't know how to interrupt the task.
    sol = nothing
end

see this post

...
if istaskdone(tsk1)
    sol = fetch(tsk1)
else 
    schedule(tsk1, ErrorException("stop"), error=true)
    sol = nothing
end

will make your example work, but personally I would avoid such a hack

Thanks a lot :grinning:
But it doesn’t seem to interrupt the task. The memory is still being used, and i almost could not do anything.

...
julia> run(`free -h`)
              total        used        free      shared  buff/cache   available
Mem:           15Gi       2.3Gi        11Gi        42Mi       1.3Gi        12Gi
Swap:          15Gi       1.9Gi        14Gi
Process(`free -h`, ProcessExited(0))

julia> max_runtime = 10.0
10.0

julia> tsk1 = Base.Threads.@spawn solve(prob, Tsit5())
Task (runnable) @0x00007f3faf21bd00

julia> timedwait(() -> istaskdone(tsk1), max_runtime)
:timed_out

julia> if istaskdone(tsk1)
           sol = fetch(tsk1)
       else 
           schedule(tsk1, ErrorException("stop"), error=true)
           sol = nothing
       end

julia> sleep(40)

julia> run(`free -h`)
              total        used        free      shared  buff/cache   available
Mem:           15Gi       8.7Gi       5.4Gi        38Mi       1.3Gi       6.4Gi
Swap:          15Gi       1.9Gi        14Gi
Process(`free -h`, ProcessExited(0))

julia> istaskdone(tsk1)
false

that’s the reason why I would avoid such a way doing this. Why not using the callback as suggested?

1 Like

Thanks a lot. :grinning:
I have thought it is a basic function, such as ps, job, kill in SHELL.
Thank you once again. :yum: