在 Julia 中设置算法的时间限制
Set a time limitation on algorithm in Julia
我有一个 Julia 代码,运行 有一段时间了。我想 运行 代码 3 小时,然后终止它。有谁知道最有效的方法是什么。将不胜感激任何建议。谢谢
@async 和@sync 对于 Julia 中的协程类型流程控制非常有用。您可以启动一个异步进程,稍后调用 exit 以终止整个程序:
function killafterseconds(s)
@async begin
sleep(s)
println("terminating after $s seconds")
exit(0)
end
end
function countdown(n)
for t in n:-1:0
println(t)
sleep(1)
end
end
killafterseconds(10)
countdown(10000)
我建议使用 Distributed
将您的函数生成为一个新进程并控制它的时间(我相信我一直在回答类似的问题,但我找不到答案)。
代码如下:
using Distributed
function run_with_timeout(timeout::Int,f::Function, wid::Int)
result = RemoteChannel(()->Channel{Tuple}(1));
@spawnat wid put!(result, (f(),myid()))
res = (:timeout, wid)
time_elapsed = 0.0
while time_elapsed < timeout && !isready(result)
sleep(0.5)
time_elapsed += 0.5
end
if !isready(result)
println("Timeout! at $wid")
else
res = take!(result)
end
return res
end
你可以这样使用(请注意外部包是如何导入的):
wid = addprocs(1)[1]
@everywhere using DataFrames
@everywhere function ff()
sleep(2)
#code fir making heavy computations
#this is the place to write whatever you need
return DataFrame(x=[1,2],y=[1,3])
end
现在让我们运行吧。请注意,第二个返回值是 运行 计算的 workerid(您可能想删除它):
julia> run_with_timeout(10,() ->(try;ff();catch ee;dump(ee);end ),wid)
(2×2 DataFrame
│ Row │ x │ y │
│ │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 3 │, 2)
如果我们只给代码 1 秒来执行它将失败:
julia> run_with_timeout(1,() ->(try;ff();catch ee;dump(ee);end ),wid)
Timeout! at 2
(:timeout, 2)
最后,由于发生超时,进程应该被杀死(否则它会继续执行):
rmprocs(wid)
这是一个使用线程的解决方案。我只是乞求在 Julia 中编码,所以它不是高质量的代码,但它可以工作。您首先需要使用 @task 宏将函数包装为任务,然后调用 runTask():
function runTask(origtask:: Task, timeoutms:: Int)
startTime = Dates.datetime2epochms(now())
function internal_task(taskFinished)
try
schedule(origtask)
yield()
wait(origtask)
if istaskdone(origtask)
taskFinished[] = true
Base.task_result(origtask)
else
throw(ErrorException("Task is not done even after wait() for it to finish - something is wrong"))
end
catch e
@warn "Error while processing task: $e"
taskFinished[] = true
missing
end
end
taskFinished = Threads.Atomic{Bool}(false)
thread = Threads.@spawn internal_task(taskFinished)
while !taskFinished[] && (Dates.datetime2epochms(now()) - startTime) < timeoutms
sleep(0.1)
end
if taskFinished[]
return fetch(thread)
end
# Task timeouted
origtask.exception = InterruptException()
return missing
end # function
此代码最糟糕的部分是使用 sleep(0.1) 主动等待。我想我可以通过再生成一个线程来摆脱它,所以总共有 3 个:一个执行 origtask 的实际工作,完成后通知一个条件,一个等待提到的条件,另一个将休眠超时秒数,然后通知条件。
我有一个 Julia 代码,运行 有一段时间了。我想 运行 代码 3 小时,然后终止它。有谁知道最有效的方法是什么。将不胜感激任何建议。谢谢
@async 和@sync 对于 Julia 中的协程类型流程控制非常有用。您可以启动一个异步进程,稍后调用 exit 以终止整个程序:
function killafterseconds(s)
@async begin
sleep(s)
println("terminating after $s seconds")
exit(0)
end
end
function countdown(n)
for t in n:-1:0
println(t)
sleep(1)
end
end
killafterseconds(10)
countdown(10000)
我建议使用 Distributed
将您的函数生成为一个新进程并控制它的时间(我相信我一直在回答类似的问题,但我找不到答案)。
代码如下:
using Distributed
function run_with_timeout(timeout::Int,f::Function, wid::Int)
result = RemoteChannel(()->Channel{Tuple}(1));
@spawnat wid put!(result, (f(),myid()))
res = (:timeout, wid)
time_elapsed = 0.0
while time_elapsed < timeout && !isready(result)
sleep(0.5)
time_elapsed += 0.5
end
if !isready(result)
println("Timeout! at $wid")
else
res = take!(result)
end
return res
end
你可以这样使用(请注意外部包是如何导入的):
wid = addprocs(1)[1]
@everywhere using DataFrames
@everywhere function ff()
sleep(2)
#code fir making heavy computations
#this is the place to write whatever you need
return DataFrame(x=[1,2],y=[1,3])
end
现在让我们运行吧。请注意,第二个返回值是 运行 计算的 workerid(您可能想删除它):
julia> run_with_timeout(10,() ->(try;ff();catch ee;dump(ee);end ),wid)
(2×2 DataFrame
│ Row │ x │ y │
│ │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 3 │, 2)
如果我们只给代码 1 秒来执行它将失败:
julia> run_with_timeout(1,() ->(try;ff();catch ee;dump(ee);end ),wid)
Timeout! at 2
(:timeout, 2)
最后,由于发生超时,进程应该被杀死(否则它会继续执行):
rmprocs(wid)
这是一个使用线程的解决方案。我只是乞求在 Julia 中编码,所以它不是高质量的代码,但它可以工作。您首先需要使用 @task 宏将函数包装为任务,然后调用 runTask():
function runTask(origtask:: Task, timeoutms:: Int)
startTime = Dates.datetime2epochms(now())
function internal_task(taskFinished)
try
schedule(origtask)
yield()
wait(origtask)
if istaskdone(origtask)
taskFinished[] = true
Base.task_result(origtask)
else
throw(ErrorException("Task is not done even after wait() for it to finish - something is wrong"))
end
catch e
@warn "Error while processing task: $e"
taskFinished[] = true
missing
end
end
taskFinished = Threads.Atomic{Bool}(false)
thread = Threads.@spawn internal_task(taskFinished)
while !taskFinished[] && (Dates.datetime2epochms(now()) - startTime) < timeoutms
sleep(0.1)
end
if taskFinished[]
return fetch(thread)
end
# Task timeouted
origtask.exception = InterruptException()
return missing
end # function
此代码最糟糕的部分是使用 sleep(0.1) 主动等待。我想我可以通过再生成一个线程来摆脱它,所以总共有 3 个:一个执行 origtask 的实际工作,完成后通知一个条件,一个等待提到的条件,另一个将休眠超时秒数,然后通知条件。