I have a Julia code where I need to execute two operation in a parallel way. My problem is that I need to stop and kill one operation if it take too much time.
I tried with the Task
but now I can't find how to kill a task. My code is:
function mytask(myargs, ch)
# do some work (optimize a problem with Gurobi)
# that can go on for a very long time
put!(ch, computationResult)
end
ch = Channel(1)
task = @async mytask(args, ch)
# now the main task does some other work
# and at the end
if isready(ch)
taskResult = take!(ch)
else
# the result of th async task became useless
# so here I need to kill the async task
end
# continue the execution
I found this similar old question but I think the solution is no longer supported because I can't find the throwto
method in the documentation and I also tried it but I get this error message
WARNING: Workqueue inconsistency detected: shift!(Workqueue).state != :queued
ERROR (unhandled task failure): InterruptException:
I'm not forced to use tasks, I can use thread processes or any other solution as long as it works
You wrote that while waiting for long computation to finish you need to do some other processing in the foreground. @async
provides green-threading mechanism only and hence is inappropriate for your problem - your program would be still able to use only one Thread
at a time. Additionally, currently in Julia tasks do not support killing mechanism (unless you do it in some way programmatically yourself).
The clean solution is to use the Julia Distributed
mechanism. Below is a sample code snippet.
The code starts long-running computations - depending on whether the computation finishes within the declared time the results or collected or the process is killed.
Enjoy!
using Distributed
Distributed.addprocs(1) #we add one worker process that will be the
#long-running background computation
wid = workers()[end] #take last worker (there is just one anyway)
const result = RemoteChannel(()->Channel{Tuple}(1));
@everywhere function longrun(result,c=3,time=0)
#write whatever code you need here
for i in 1:c
sleep(time)
println("Working $i at $(myid())")
end
#we use the RemoteChannel to collect the result
put!(result, (c,time,999999, myid()))
end
function ready_or_not(result,wid)
if !isready(result)
println("Computation at $wid will be terminated")
rmprocs(wid)
return nothing
else
return take!(result)
end
end
remote_do(longrun,wid,result) #this takes far less than a second...
sleep(1)
show(ready_or_not(result,wid)) # .. and you should see the result
remote_do(longrun,wid,result,10,3) #this takes 30s
sleep(7)
show(ready_or_not(result,wid)) #ready_or_not() terminates the worker process
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With