我使用foreach进行并行处理,这需要通过列表手动将函数传递到已寻址内核的环境。我希望自动执行此过程并涵盖所有用例。易于使用仅包含变量的简单函数。然而,一旦要并行处理的函数使用在另一个环境中定义的参数和变量,就会出现并发症。考虑以下情况:
global.variable <- 3
global.function <-function(j){
res <- j^2
return(res)
}
compute.in.parallel <-function(i){
res <- global.function(i+global.variable)
return(res)
}
pop <- seq(10)
do <- function(pop,fun){
require(doParallel)
require(foreach)
cl <- makeCluster(16)
registerDoParallel(cl)
clusterExport(cl,list("global.variable","global.function"),envir=globalenv())
results <- foreach(i=pop) %dopar% fun(i)
stopCluster(cl)
return(results)
}
do(pop,compute.in.parallel)
这是有效的,因为我手动将global.variable和global.function传递给核心(请注意,compute.in.parallel本身在范围内自动考虑):
clusterExport(cl,list("global.variable","global.function"),envir=globalenv())
但我想自动完成 - 要求在compute.in.parallel
内构建一个所有变量和函数的字符串(但未定义/传递/包含)。我该怎么做?
我目前的解决方法是将所有可用变量转储到核心:
clusterExport(cl,as.list(unique(c(ls(.GlobalEnv),ls(environment())))),envir=environment())
然而,这并不令人满意 - 我没有考虑包命名空间和其他隐藏环境中的变量,也没有考虑将太多变量传递给核心,从而在每次并行运行时都会产生很大的开销。
有任何建议的改进吗?
答案 0 :(得分:2)
只需传递do()中所需的所有参数,而不是使用全局变量。
compute.in.parallel <- function(i, global.variable, global.function) {
global.function(i + global.variable)
}
do <- function(pop, fun, ncores = parallel::detectCores() - 1, ...) {
require(foreach)
cl <- parallel::makeCluster(ncores)
on.exit(parallel::stopCluster(cl), add = TRUE)
doParallel::registerDoParallel(cl)
foreach(i = pop) %dopar% fun(i, ...)
}
do(seq(10), compute.in.parallel,
global.variable = 3,
global.function = function(j) j^2)
答案 1 :(得分:1)