2

我正在尝试复制未来包的拓扑插图中的示例。去引用:

期货可以嵌套在 R 中,这样一个未来会创建另一组期货,依此类推。例如,这可能发生在嵌套的 for 循环中 [...]

有一部分作者使用plan(list(multicore, multicore))(进一步的论点并tweak省略)同步处理两个期货,每个期货同步处理四个期货。这应该等于同步处理的八个期货。

但是,当我尝试使用下面的代码重现这一点时,我看到第二级期货是按顺序处理的。我究竟做错了什么?

MCVE

library(future)
library(ggplot2)
plan(list(multiprocess, multiprocess))


# Run for a random amount of time and return start and stop time
startStop <- function(){
  start <- Sys.time()
  x <- runif(1, 1, 3)
  Sys.sleep(x)
  stop <- Sys.time()
  return(data.frame(start = start, stop = stop))
}

nGrp <- 3
nCV <- 4

l <- rep(list(NULL), nGrp)


for(i in seq_along(l)){
  l[[i]] <- future({
    m <- rep(list(NULL), nCV)
    for(j in seq_along(m)){
      m[[j]] <- future(startStop())
    }
    m <- lapply(m, value)
    m <- do.call(rbind, m)
    m
  })
}
l <- lapply(l, value)
d <- do.call(rbind, l)
d$iGrp <- rep(seq_len(nGrp), each = nCV)
d$iCV <- rep(seq_len(nCV), times = nGrp)

d$x <- paste(d$iGrp, d$iCV, sep = "_")
d$iGrp <- as.character(d$iGrp)
ggplot(d, aes(x = x, ymin = start, ymax = stop, color = iGrp)) + geom_linerange() + coord_flip()

期货执行的时间演变

期待

期待

会话信息

R version 3.4.3 (2017-11-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS: /opt/Bio/R/3.4.3/lib64/R/lib/libRblas.so
LAPACK: /opt/Bio/R/3.4.3/lib64/R/lib/libRlapack.so

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

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

other attached packages:
[1] ggplot2_2.2.1 future_1.8.1 

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.17     devtools_1.13.4  munsell_0.4.3    colorspace_1.3-2
 [5] R6_2.2.2         rlang_0.1.6      httr_1.3.1       plyr_1.8.4      
 [9] globals_0.11.0   tools_3.4.3      parallel_3.4.3   grid_3.4.3      
[13] gtable_0.2.0     git2r_0.21.0     withr_2.1.1      yaml_2.1.16     
[17] lazyeval_0.2.1   digest_0.6.15    tibble_1.4.2     codetools_0.2-15
[21] curl_3.1         memoise_1.1.0    compiler_3.4.3   pillar_1.1.0    
[25] scales_0.5.0     listenv_0.7.0 
4

2 回答 2

3

未来的作者在这里:这是因为有针对嵌套并行性的内置保护。没有它,您的计算机会因过多的并行进程而过载,这不仅会使其过热,还会降低整体性能。

我已使用以下部分更新了下一个版本的“未来拓扑”插图:

针对递归并行的内置保护

上面我们已经并行处理了外部或内部未来集。如果我们想并行处理两个层怎么办?很想使用:

plan(list(multiprocess, multiprocess))

虽然这不会出错,但我们会发现期货的内层将被顺序处理,就像我们使用plan(list(multiprocess, sequential)). 这种行为是由于对嵌套并行性的内置保护。如果两层并行运行,每层都使用机器上可用的 8 个内核,我们将运行 8 * 8 = 64 个并行进程——这肯定会使我们的计算机过载。内部发生的情况是,对于外层,availableCores()等于八 (8),而对于内层,它等于一 (1)。

现在,我们可以想象我们用两个平行的期货来处理外层,然后用四个平行的期货来处理内层。在这种情况下,我们最终会在最多八个内核 (= 2 * 4) 上运行。这可以通过在每一层强制使用固定数量的工人来实现(不推荐):

plan(list(tweak(multiprocess, workers = 2), tweak(multiprocess, workers = 4)))
于 2018-06-12T23:36:01.220 回答
1

如果你想像你预期的那样实现并行处理, future.callr是不二之选。只需使用: library(future.callr) plan(list(callr, callr))

于 2018-06-13T02:10:59.867 回答