如何提前终止本次循环

最近在用DifferentialEquations.jl包求解常微分方程组。由于要对其中的参数优化,就写了一个opt(pars) 函数,返回一个值。然后用Optim.jl包去优化这个opt(pars) 函数,从而得到最佳的pars

但是有时候DifferentialEquations.jlsolve(prob) 求解某些参数组合时会非常慢。可能会超过好几个小时。我想在opt(pars) 这个函数中添加一些内容,可以设定solve(prob) 执行时间超过60s后,如果solve(prob) 没有运行完,就返回一个特定值;如果solve(prob) 求解完成则返回求解的结果。

看起来python中的 eventlet可以完成这个事情。但是我不太了解python。

Julia中类似有类似的包吗? :grinning:
或者其他可以实现的方法? :grinning:

去slack问了一下,好像没有,如果有的话我再次回复
不知道你这个库的文档里有没有提到加速

多谢 :smiley:
没有看到这个库里面又说道加速这个问题。
我有看到类似的:
https://www.coder.work/article/6981898

max_runtime = 10*60 # 10 minutes
for k = 1:10
    proc = spawn(`program inputs`)
    timedwait(() -> process_exited(proc), max_runtime)
    if process_running(proc)
        kill(proc)
    end
end

不过我没有找到spawn这个函数。我试了Base.Theads.@spawn,不过返回来的proc是一个Task类型;如果用的是Distributed.@spawn,返回的是Future类型。后面的process_exited和process_running都要求参数是Process类型。因此会报错。
我不是很了解这些多线程运行的问题,不知道是不是哪里理解的不对。

我试了一下,可以用Base.Threads.@spawn将Task放在“后台”运行。不过我好像没有办法终止这个Task。

...
tsk1 = Base.Threads.@spawn solve(prob, Tsit5())
timedwait(() -> istaskdone(tsk1), max_runtime)
if istaskdone(tsk1)
    sol = fetch(tsk1)
else 
    schedule(tsk1, ErrorException("stop"), error=true) # Not work
    sol = nothing
end

我试了Distributed中的interrupt(),还有 Base.throwto(tsk1,InterruptException()) ,以及schedule(tsk1, ErrorException("stop"), error=true)。这些方法似乎都不能终止tsk1的运行。占用了很高的内存,导致我几乎别的事情都不能做 :pensive:

那个连接应该是复制的这个问题的答案:

但正如原题所说,它要是调用外部命令启动另一个外部进程(Process类型表示的东西),和你的问题并不相同,其中spawn之所以没用本身被run取代了:

如果你启动了一个进程你可以用Distributed.rmprocs终止整个进程

https://docs.julialang.org/en/v1/stdlib/Distributed/#Distributed.rmprocs

虽然我怀疑这么做有什么用处,你应该throwto之后继续复用那个进程而不是关了重开浪费初始化进程的时间。

因为我用的是DifferentialEquations.jl包中的solve。后来他们推荐使用callback来终止长时间的求解常微分方程组。

尽管这个方法对我目前是有效的。不过我还是有些好奇通用一些的方法来提前终止程序。 :smiley:

1 个赞

我再多提供一种可能的途径吧。以下文档:

Event Handling and Callback Functions