2016-03-01 63 views
3

下面的问题是一个非常详细的问题与这里描述的问题有关。 Previous QuestionR doParallel foreach工人超时错误,永不返回

使用Ubuntu Server 14.04 LTS 64位亚马逊机器映像在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循环将无限期地继续。达到累计时间后,将返回“超时2失败”并继续执行脚本。

问题:如果以这样的方式,即使是个别超时机制不起作用,一个人如何重新启动工人,以便它可以继续单独的工作进程“挂起”在并行处理中使用?如果无法重新启动工作人员,工作人员能否以达到累计超时时间的方式停止工作?这样做可以确保进程在延长的时间内不会持续“等待”达到累积超时,而只有单个“错误”进程正在运行。

其他信息 A“逃跑”过程或“挂起”工人被当场抓获。使用htop查看进程,它具有以100%CPU运行的状态。下面的链接是GDB回溯通话的过程

backtrace screenshot

问题截图:就是在回溯确定了“失控”进程的原因是什么?

回答

0

我多次尝试让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. 切记妥善保存您的错误极好的选择消息在某处有用并对其进行格式化,以便您可以看到真正发生的情况。