我正在使用此处发布的示例代码来显示具有doParallel
+foreach
的progress_bar
(来自progress
包)。然而,那里的解决方案利用了doSNOW
(例如我用于测试的杜威布鲁克的代码),它比doParallel
更过时,并在构建带有 CRAN 标志的包时返回以下注释:
使用被取代的软件包:"doSNOW (>= 1.0.19)">
改变这一点似乎并不像预期的那样简单。如果只有registerDoSNOW
被registerDoParallel
替换,并且.options.snow
.options.doparallel
代码将运行,但在第二种情况下根本不会显示任何进度条。
我认为这可能与.options.X
的使用有关。这部分代码对我来说非常晦涩,因为.options.snow
在使用doSNOW
时确实有效,但是没有关于使用此参数的foreach
手册页的文档。因此,.options.doparallel
不起作用也就不足为奇了,因为这只是我的一个疯狂猜测。
在foreach
循环中包含对pb$tick()
的调用也不起作用,并且实际上会导致结果错误。所以我真的不知道我应该在代码中的什么位置包含它。
.options.snow
从何而来?pb$tick()
应该去哪里,如何在这里使用doParallel
显示progress_bar
对象?
为了方便起见,我粘贴在代码下方(doSNOW
替换为doParallel
),但再次注明原始来源:
library(parallel)
library(doParallel)
numCores<-detectCores()
cl <- makeCluster(numCores)
registerDoParallel(cl)
# progress bar ------------------------------------------------------------
library(progress)
iterations <- 100 # used for the foreach loop
pb <- progress_bar$new(
format = "letter = :letter [:bar] :elapsed | eta: :eta",
total = iterations, # 100
width = 60)
progress_letter <- rep(LETTERS[1:10], 10) # token reported in progress bar
# allowing progress bar to be used in foreach -----------------------------
progress <- function(n){
pb$tick(tokens = list(letter = progress_letter[n]))
}
opts <- list(progress = progress)
# foreach loop ------------------------------------------------------------
library(foreach)
foreach(i = 1:iterations, .combine = rbind, .options.doparallel = opts) %dopar% {
summary(rnorm(1e6))[3]
}
stopCluster(cl)
无论出于何种原因,doParallel
仍然使用.options.snow
参数。在doParallel文档中找到了这个小花絮。
doParallel 后端支持通过 foreach 函数传递的多核和 snow 选项。支持的多核选项是第一
preschedule
、set.seed
、silent
和cores
,它们类似于与mclapply
类似名称的参数,并使用.options.multicore
参数传递给foreach。支持的snow选项是preschedule
,就像它的多核模拟一样,可以用来对任务进行分块,以便每个工作线程获得预先计划的任务块,以及attachExportEnv
,可用于在R的词法范围无法找到所需的导出的某些情况下附加导出环境。雪选项使用.options.snow
参数传递给 foreach。
foreach
是一个强大的软件包,但维护它的人会做出奇怪的决定。
>编辑doParallel
不支持progress
多核选项。因此,如果使用进度条而不是registerDoSNOW
,则不会显示进度条registerDoParallel
。
虽然doSNOW
已被取代,但目前还不清楚一个是否比另一个更过时,因为两者都经历了很少的更改,而不是更新当前的维护者(doParallel | doSNOW)。
doSNOW
doSNOW:::doSNOW <- function (obj, expr, envir, data)
{
cl <- data
preschedule <- FALSE
attachExportEnv <- FALSE
progressWrapper <- function(...) NULL # <- CRITICAL DIFFERENCE
if (!inherits(obj, "foreach"))
stop("obj must be a foreach object")
it <- iter(obj)
accumulator <- makeAccum(it)
options <- obj$options$snow
if (!is.null(options)) {
nms <- names(options)
recog <- nms %in% c("preschedule", "attachExportEnv",
"progress") # <- CRITICAL DIFFERENCE
if (any(!recog))
warning(sprintf("ignoring unrecognized snow option(s): %s",
paste(nms[!recog], collapse = ", ")), call. = FALSE)
...
doParallel
doParallel:::doParallelSNOW <- function (obj, expr, envir, data)
{
cl <- data
preschedule <- FALSE
attachExportEnv <- FALSE
# MISSING: progressWrapper <- function(...) NULL
if (!inherits(obj, "foreach"))
stop("obj must be a foreach object")
it <- iter(obj)
accumulator <- makeAccum(it)
options <- obj$options$snow
if (!is.null(options)) {
nms <- names(options)
recog <- nms %in% c("preschedule", "attachExportEnv" #MISSING , "progress")
if (any(!recog))
warning(sprintf("ignoring unrecognized snow option(s): %s",
paste(nms[!recog], collapse = ", ")), call. = FALSE)
...