如何停止R中花费太长时间的函数并为其提供替代方案?
我想用“正确的方式”做一件事。有时,“正确的方法”需要太长时间,这取决于输入。我真的不知道什么时候会这样。当“正确的方式”花费的时间太长时,我想选择“黑客方式”。我如何让R监视一个特定任务所花费的时间,并在超过阈值时给它一些其他的事情去做?我想这将是如何停止R中花费太长时间的函数并为其提供替代方案?,r,time,error-handling,R,Time,Error Handling,我想用“正确的方式”做一件事。有时,“正确的方法”需要太长时间,这取决于输入。我真的不知道什么时候会这样。当“正确的方式”花费的时间太长时,我想选择“黑客方式”。我如何让R监视一个特定任务所花费的时间,并在超过阈值时给它一些其他的事情去做?我想这将是try家族的一部分,但我不太确定该如何称呼它或谷歌 下面是一个虚拟示例。当slow.func花费的时间太长时,我希望interuptor停止它并调用fast.func slow.func <- function(x){ Sys.slee
try
家族的一部分,但我不太确定该如何称呼它或谷歌
下面是一个虚拟示例。当slow.func
花费的时间太长时,我希望interuptor
停止它并调用fast.func
slow.func <- function(x){
Sys.sleep(x)
print('good morning')
}
fast.func <- function(x){
Sys.sleep(x/10)
print('hit snooze')
}
interuptor = function(FUN,args, time.limit, ALTFUN){
# START MONITORING TIME HERE
do.call(FUN,args)
# IF FUN TAKES TOO LONG, STOP IT, CALL A
do.call(ALTFUN,args)
}
interuptor(slow.func, list(x = 2), time.limit = 1, fast.func)
slow.funcR包R.utils
有一个函数evalWithTimeout
,这正是您所描述的。如果您不想安装软件包,evalWithTimeout
依赖于用户不太友好的R base函数setTimeLimit
您的代码如下所示:
library(R.utils)
slow.func <- function(x){
Sys.sleep(10)
return(x^2)
}
fast.func <- function(x){
Sys.sleep(2)
return(x*x)
}
interruptor = function(FUN,args, time.limit, ALTFUN){
results <- NULL
results <- evalWithTimeout({FUN(args)},timeout=time.limit,onTimeout="warning")
if(results==NULL){
results <- ALTFUN(args)
}
return(results)
}
interruptor(slow.func,args=2,time.limit=3,fast.func)
库(R.utils)
slow.func我发布的初始版本使用了“R.utils v2.5.0(2016-11-07)”,但没有使用“R.utils v2.9.2”。下面是使用“R.utils v2.9.2”进行了一些修改的版本
带有“R.utils v2.5.0”的版本
“nwknoblauch”的答案对我不起作用,除非我在中断器函数中通过“静默”更改“警告”
library(R.utils)
slow.func <- function(x){
Sys.sleep(10)
return(x^2)
}
fast.func <- function(x){
Sys.sleep(2)
return(x*x)
}
interruptor = function(FUN,args, time.limit, ALTFUN){
results <- NULL
results <- evalWithTimeout({FUN(args)},timeout=time.limit,onTimeout="silent")
if(is.null(results)){
results <- ALTFUN(args)
}
return(results)
}
interruptor(FUN = slow.func,args=2,time.limit=3,ALTFUN = fast.func)
库(R.utils)
slow.func对于任何想要不依赖于R.utils
包的更轻量级解决方案的人,我最终使用了基于withTimeout()
代码的最小解决方案
foo <- function() {
time_limit <- 10
setTimeLimit(cpu = time_limit, elapsed = time_limit, transient = TRUE)
on.exit({
setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
})
tryCatch({
# do some stuff
}, error = function(e) {
if (grepl("reached elapsed time limit|reached CPU time limit", e$message)) {
# we reached timeout, apply some alternative method or do something else
} else {
# error not related to timeout
stop(e)
}
})
}
foo如何添加时间检查?是的,我只是在运行R。我还没有学过任何C。在这种情况下,编写和编译一个简单的C程序并用.C
调用它会很简单吗?不起作用:错误:“evalWithTimeout”已失效。改为使用“R.utils::withTimeout()”。请参阅帮助(“已失效”)
时间流逝和版本更改。我修改了这个函数,它似乎又能工作了。我目前正在使用R版本3.6.0和R.utils v2.9.2
test_obj <- interruptor(FUN = slow.func, args=5, time.limit= 6, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args=5, time.limit= 3, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args="A", time.limit= 6, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args="A", time.limit= 3, ALTFUN = fast.func)
test_obj
foo <- function() {
time_limit <- 10
setTimeLimit(cpu = time_limit, elapsed = time_limit, transient = TRUE)
on.exit({
setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
})
tryCatch({
# do some stuff
}, error = function(e) {
if (grepl("reached elapsed time limit|reached CPU time limit", e$message)) {
# we reached timeout, apply some alternative method or do something else
} else {
# error not related to timeout
stop(e)
}
})
}