【问题标题】:mclapply fails with data.tablemclapply 因 data.table 失败
【发布时间】:2019-07-24 08:19:24
【问题描述】:

我目前遇到了一个奇怪的情况,我使用 mclapply 并行化了一个循环。

并行调用有时会使用 mclapply 返回 NULL,但当我使用 lapply 时一切正常。

使用 mclapply 也可以解决问题,但前提是我不在调用的函数中使用 data.table 进行子集化。

我还没有可以在此处发布的合理 mve,但可以根据要求提供代码。

简化的一般结构如下所示:

foo <- function(d) { # d is a data.table
    unlist(mclapply(1:nrow(d), function(i) bar(d[-i])))
}


bar <- function(d) {    
    ...
    ## this version fails:
    pdists <- lapply(unique(d$comp),
                     function(cc) dist(d[d$comp==cc,.(X,Y)]))
    ## this also fails:
    pdists <- lapply(unique(d$comp),
                     function(cc) dist(d[cc, .(X,Y), on="comp"]))
    ## this way it works:
    pdists <- lapply(unique(d$comp),
                     function(cc) dist(d[d$comp==cc,c("X","Y")]))
    ...
}

当查看 mclapply 返回的内容并检查哪些元素为 NULL 时,我得到:

  write error, closing pipe to the master
  [1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE TRUE FALSE
 [13] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE TRUE FALSE
 [25] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE TRUE FALSE
...
[337] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE TRUE FALSE
[349] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE TRUE FALSE

这几乎看起来像四个线程之一死了(我使用 mc.cores=4)。

data.table 中是否存在线程安全问题?

(我已经在两台不同的电脑上重现了这个问题)

> sessionInfo()                                                                                                                                           
R version 3.5.2 (2018-12-20)                                                                                                                              
Platform: x86_64-pc-linux-gnu (64-bit)                                                                                                                    
Running under: Ubuntu 18.04.2 LTS                                                                                                                         

Matrix products: default                                                                                                                                  
BLAS: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3                                                                                                   
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3                                                                                               

locale:                                                                                                                                                   
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C                                                                                                              
 [3] LC_TIME=en_DK.utf8         LC_COLLATE=en_US.UTF-8                                                                                                    
 [5] LC_MONETARY=de_CH.UTF-8    LC_MESSAGES=en_US.UTF-8                                                                                                   
 [7] LC_PAPER=de_CH.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=de_CH.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] data.table_1.12.0

通过命名空间加载(未附加): [1] 编译器_3.5.2 工具_3.5.2

更新:根据@jangorecki 的评论,我添加了setDTthreads(1),但错误仍然存​​在。我再次尝试了不同的版本:

## works:
pdists <- lapply(split(d[,.(comp,X,Y)], by="comp", keep.by=FALSE), FUN=dist) 

## these fail:
pdists <- lapply(unique(d$comp), function(cc) dist(d[cc, .(X,Y), on="comp"]))
pdists <- lapply(unique(d$comp), function(cc) dist(d[comp==cc,.(X,Y)])) 

更新 2:有趣的是,时间也很重要。通过在被调用函数bar 中引入随机延迟,并将mc.preschedule = FALSE 作为mclapply 的参数,失败的调用数量会有所不同。

失败的总是第三次调用(mc.cores>=3),再加上多次连续调用。 mclapply返回的列表中对应的值为NULL。

对于这些调用,我还看到“sendMaster 中的错误(try(eval(expr, env),silent = TRUE)):写入错误,关闭到主机的管道”。我发现令人不安的是,这些调用会默默地失败,而不会停止执行。

【问题讨论】:

  • 为什么不d[comp==cc, ...]?为什么不lapply(split(d[,c("comp","X","Y")], by="comp"), dist)tmp 是什么?
  • tmp 应该在这里 -> 更正。也好点 lapply/split。问题仍然存在:为什么其中一名工人返回 NULL(因为我想它死了)。
  • 如果您设置setDTthreads(1),您能否检查问题是否仍然存在?在调用您的脚本之前,在新会话中仔细检查设置
  • @jangorecki:我根据您的建议用测试更新了这个问题。将 DTthreads 设置为 1 并不能解决问题。
  • 我面临着类似的情况,我将 mclapply 应用在一个分成 30000 个块和 20 个核心的 data.table 上。那么有什么解决办法吗?

标签: r data.table mclapply


【解决方案1】:

无法访问您的 data.table,我希望您的问题是 dist 对某些组失败(可能它们太小),并且分配给同一核心的所有其他组都被“污染”一组返回错误,mclapply 的记录行为也是如此,如https://stackoverflow.com/a/57979216/415228 中更完整的描述。

【讨论】:

    猜你喜欢
    • 2014-04-05
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 2013-06-26
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多