是否应嵌套mclapply调用?

时间:2018-08-06 12:16:44

标签: r parallel-processing mclapply

嵌套parallel::mclapply是个好主意吗?

require(parallel)
ans <- mclapply(1:3, function(x) mclapply(1:3, function(y) y * x))
unlist(ans)

输出:

[1] 1 2 3 2 4 6 3 6 9

所以它正在“工作”。但是,是否建议将其用于实际的计算密集型任务,而不是内核数?执行此操作时会发生什么情况?涉及的多个分叉是否更可能造成浪费? mc.coresmc.preschedule的注意事项是什么?

修改 只是为了阐明动机,通过拆分一个维度来进行并行化似乎很自然(例如,使用不同的内核来处理不同年份的数据),然后在拆分中又出现了另一种自然的拆分方式(例如,请使用不同的内核来计算 m 个不同函数中的每个函数)。当m乘以n小于可用核的总数时,至少在表面看来,上述嵌套是明智的。

1 个答案:

答案 0 :(得分:1)

在以下实验中,测试功能testfn() parallel 执行比嵌套并行执行更快:

library(parallel)
library(microbenchmark)
testfn <- function(x) rnorm(10000000)

microbenchmark('parallel'= o <- mclapply(1:8, testfn, mc.cores=4),
               'nested'  = o <- mclapply(1:2, function(x) mclapply(1:4, testfn, mc.cores=2), 
                                         mc.cores=2),
               times=10)
Unit: seconds
     expr      min       lq     mean   median       uq      max neval
 parallel 3.727131 3.756445 3.802470 3.815977 3.834144 3.890128    10
   nested 4.355846 4.372996 4.508291 4.453881 4.578837 4.863664    10

说明
R会话与四个R工作者之间的通信似乎比R会话与两个工作者之间的通信更有效,后者又分叉并分别与另外两个工作者进行通信。

替代
foreach 可以处理嵌套循环,它接近嵌套的mclapply()调用;参见小插图https://cran.r-project.org/web/packages/foreach/vignettes/nested.pdf

(参数mc.preschedule的最佳设置取决于特定的问题;请参见帮助页面?mclapply。)