Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to kill a task in Julia?

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

like image 683
mda Avatar asked Aug 25 '18 14:08

mda


1 Answers

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.

like image 89
Przemyslaw Szufel Avatar answered Oct 30 '22 20:10

Przemyslaw Szufel