R doParallel foreach worker超时错误,永不返回

以下问题是与此处描述的问题相关的非常详细的问题.
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调用的屏幕截图

backtrace screenshot

问题:回溯中是否确定了“失控”过程的原因?

最佳答案 我多次尝试让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更详细的输出
>请记住将错误消息保存在有用的地方并格式化,以便您可以看到实际发生的情况.

点赞