以下问题是与此处描述的问题相关的非常详细的问题.
Previous Question
使用Ubuntu Server 14.04 LTS 64位Amazon Machine Image在c4.8xlarge(36核)上推出,版本为3.2.3.
请考虑以下代码
library(doParallel)
cl=makeCluster(35)
registerDoParallel(cl)
tryCatch({
evalWithTimeout({
foreach(i=1:10) %:%
foreach(j=1:50) %dopar% {
tryCatch({
evalWithTimeout({
set.seed(j)
source(paste("file",i,".R", sep = "")) # File that takes a long time to run
save.image(file=paste("file", i, "-run",j,".RData",sep=""))
},
timeout=300); ### Timeout for individual processes
}, TimeoutException=function(ex) {
return(paste0("Timeout 1 Fail ", i, "-run", j))
})
}
},
timeout=3600); ### Cumulative Timeout for entire process
}, TimeoutException=function(ex) {
return("Timeout 2 Fail")
})
stopCluster(cl)
请注意两个超时异常都有效.我们注意到单个进程超时,并在必要时累积进程超时.
但是,我们发现单个进程可以启动并且由于未知原因在300秒后不会超时.请注意,单个进程超时可确保该进程不会“花费很长时间”.因此,核心将被此单个进程占用并以100%运行,直到达到3600秒的累积超时.请注意,如果累积超时未到位,则进程及其核心将被无限期占用,并且foreach循环将无限期地继续.达到累积时间后,将返回“Timeout 2 Fail”并继续执行脚本.
问题:如果单个工作进程以某种方式“挂起”,即使单个超时机制不起作用,如何重新启动工作程序以便它可以继续用于并行处理?如果无法重新启动工作人员,那么工作人员是否可以以达到累积超时之外的方式停止?这样做可以确保在只有单个“错误”进程正在运行时,“等待”达到累积超时的过程中,该过程不会持续很长时间.
附加信息
一个“逃跑”过程或“挂起”的工人陷入了这一行为.使用htop查看进程,它具有100%CPU运行状态.以下链接是该进程的gdb backtrace调用的屏幕截图
问题:回溯中是否确定了“失控”过程的原因?
最佳答案 我多次尝试让evalWithTimeout在非常相似的上下文中工作.我发现这是非常有问题的,特别是如果你正在使用数据库连接或全局变量.然而,对我来说非常有效的是创建一个使用setTimeLimit的表达式.要适当地使用它,你必须在{}中将它和你的函数包装在一起.这是一个例子:
foreach(...) %dopar% {
withCallingHandlers({
setTimeLimit(360)
# your function goes here, runs for 360 seconds, or fails
},
error = function(e) {
# do stuff to capture error messages here
}
)
}
我使用withCallingHandlers,因为堆栈跟踪非常有用,可以深入了解正在发生的事情.在我的错误函数中,我通常会做适当的事情来捕获详细的错误消息,以便我可以查看事情的内容和地点.
总结一下:
> setTimeLimit通常比evalWithTimeout更可靠
>使用withCallingsHandlers为您提供了出色的错误处理选项和比tryCatch更详细的输出
>请记住将错误消息保存在有用的地方并格式化,以便您可以看到实际发生的情况.