我使用R中的snow
包在Linux操作系统上具有多台机器(3台)的SOCK
集群上执行一个函数。我试着用parLapply
和clusterApply
运行代码。
在工作层出现任何错误的情况下,工作节点的结果不会正确返回给主节点,这使得调试非常困难。我目前正在使用futile.logger
独立记录工作节点的每个心跳。结果似乎是正确计算出来的。但是,当我试图在主节点上打印结果时(在接收工作人员的输出后),我得到一个错误,上面写着Error in checkForRemoteErrors(val): 8 nodes produced errors; first error: missing value where TRUE/FALSE needed
。
有没有办法更深入地调试工人的结果?
checkForRemoteErrors
函数由parLapply
和clusterApply
调用以检查任务错误,如果任何任务失败,它将抛出错误。不幸的是,尽管它显示了错误消息,但它没有提供任何有关导致错误的工作代码的信息。但是,如果修改worker/task函数来捕获错误,则可以保留一些额外的信息,这些信息可能有助于确定错误发生的位置。
例如,下面是一个失败的简单snow程序。注意,它在创建集群时使用outfile=''
,以便显示程序的输出,这本身就是一种非常有用的调试技术:
library(snow)
cl <- makeSOCKcluster(2, outfile='')
problem <- function(i) {
if (NA)
j <- 999
else
j <- i
2 * j
}
r <- parLapply(cl, 1:2, problem)
当您执行此命令时,您将看到来自checkForRemoteErrors
的错误消息和其他一些消息,但是没有任何信息告诉您是if
语句导致了错误。为了在调用problem
时捕获错误,我们定义了workerfun
:
workerfun <- function(i) {
tryCatch({
problem(i)
},
error=function(e) {
print(e)
stop(e)
})
}
现在我们用parLapply
而不是problem
来执行workerfun
,首先将problem
导出到worker:
clusterExport(cl, c('problem'))
r <- parLapply(cl, 1:2, workerfun)
在其他消息中,我们现在看到
<simpleError in if (NA) j <- 999 else j <- i: missing value where TRUE/FALSE needed>
,其中包含生成错误的实际if
语句。当然,它不会告诉您表达式的文件名和行号,但它通常足以让您解决问题。
检查你的观察范围。观察结果是如何变化的。我注意到当有很多小数点后4 5 6时,它会抛出glm。nb。为了解决这个问题,我只需要将观测值四舍五入到小数点后两位。