【问题标题】:R doParallel foreach worker timeout error and never returnsR doParallel foreach 工作者超时错误并且永远不会返回
【发布时间】:2016-06-14 13:43:42
【问题描述】:

以下问题是与此处描述的问题相关的非常详细的问题。 Previous Question

使用 Ubuntu Server 14.04 LTS 64 位 Amazon 系统映像在带有 R 版本 3.2.3 的 c4.8xlarge(36 核)上启动。

考虑下面的代码

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”并继续执行脚本。

问题:如果一个单独的工作进程“挂起”,以至于连单独的超时机制都不起作用,如何重新启动工作进程,以便它可以继续在并行处理?如果无法重新启动worker,是否可以在达到累积超时时以外的方式停止worker?这样做可以确保进程不会在只有一个“错误”进程在运行时继续长时间“等待”达到累积超时。

其他信息 一个“逃跑”的进程或“挂起”的工人被抓到了。使用 htop 查看进程,它的状态为 100% CPU 运行。以下链接是该进程的gdb回溯调用截图

backtrace screenshot

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

【问题讨论】:

  • 我目前在运行 R/3.2.0 的大型计算集群上遇到了同样的问题。我为各个进程设置了超时异常,但也发现有些进程在设置时间后不会超时,原因不明。任何帮助将不胜感激。

标签: r foreach timeout worker doparallel


【解决方案1】:

我多次尝试让 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 是因为堆栈跟踪非常有用并且可以深入了解正在发生的事情。在我的错误函数中,我通常会适当地捕获详细的错误消息,这样我就可以查看发生了什么问题以及发生了什么问题。

总结一下:

  1. setTimeLimit 通常比 evalWithTimeout 更可靠
  2. 使用 withCallingsHandlers 为您提供了出色的错误处理选项和比 tryCatch 更详细的输出
  3. 请记住将错误消息保存在有用的地方并对其进行格式化,以便您了解实际情况。

【讨论】:

    猜你喜欢
    • 2016-04-02
    • 1970-01-01
    • 2010-10-12
    • 2012-08-19
    • 2019-12-21
    • 2015-03-07
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    相关资源
    最近更新 更多