我认为允许用户注册自己的并行后端非常重要。doParallel
后端非常便携,但是如果他们想在集群的多个节点上运行您的功能怎么办?如果他们想设置makeCluster
“outfile”选项怎么办?不幸的是,如果让并行支持透明化也会使其对您的许多用户无用。
我建议你使用该getDoParRegistered
功能查看用户是否已经注册了并行后端,如果他们没有注册,则只为他们注册一个。
这是一个例子:
library(doParallel)
parfun <- function(n=10, parallel=FALSE,
cores=getOption('mc.cores', 2L)) {
if (parallel) {
# honor registration made by user, and only create and register
# our own cluster object once
if (! getDoParRegistered()) {
cl <- makePSOCKcluster(cores)
registerDoParallel(cl)
message('Registered doParallel with ',
cores, ' workers')
} else {
message('Using ', getDoParName(), ' with ',
getDoParWorkers(), ' workers')
}
`%d%` <- `%dopar%`
} else {
message('Executing parfun sequentially')
`%d%` <- `%do%`
}
foreach(i=seq_len(n), .combine='c') %d% {
Sys.sleep(1)
i
}
}
编写它以便它仅在 if 时并行运行parallel=TRUE
,即使它们注册了并行后端:
> parfun()
Executing parfun sequentially
[1] 1 2 3 4 5 6 7 8 9 10
如果parallel=TRUE
他们还没有注册后端,那么它将为他们创建并注册一个集群对象:
> parfun(parallel=TRUE, cores=3)
Registered doParallel with 3 workers
[1] 1 2 3 4 5 6 7 8 9 10
如果再次parfun
调用 with parallel=TRUE
,它将使用之前注册的集群:
> parfun(parallel=TRUE)
Using doParallelSNOW with 3 workers
[1] 1 2 3 4 5 6 7 8 9 10
这可以通过多种方式进行改进:这只是一个简单的演示。但至少它提供了一种便利,而不会阻止用户使用其环境中可能需要的自定义选项注册不同的后端。
请注意,选择默认数量的核心/工作人员也是一个棘手的问题,也是 CRAN 维护人员关心的问题。这就是为什么我没有设置默认数量的核心detectCores()
。相反,我使用的是 使用的方法mclapply
,尽管可能应该使用不同的选项名称。
关于stopCluster
请注意,此示例有时会创建一个新的集群对象,但它永远不会通过调用来停止它stopCluster
。原因是创建集群对象可能很昂贵,所以我喜欢在多个 foreach 循环中重用它们,而不是每次都创建和销毁它们。我宁愿把它留给用户,但是,在这个例子中,用户没有办法这样做,因为他们无权访问cl
变量。
有三种方法可以处理这个问题:
- 随时呼入
stopCluster
;_parfun
makePSOCKcluster
- 编写一个附加函数,允许用户停止隐式创建的集群对象(相当于包中的
stopImplicitCluster
函数doParallel
);
- 不要担心隐式创建的集群对象。
我可能会为我自己的代码选择第二个选项,但这会使这个示例变得非常复杂。已经相当复杂了。