r语言 - 使用 doParallel + foreach 显示progress_bar



我正在使用此处发布的示例代码来显示具有doParallel+foreachprogress_bar(来自progress包)。然而,那里的解决方案利用了doSNOW(例如我用于测试的杜威布鲁克的代码),它比doParallel更过时,并在构建带有 CRAN 标志的包时返回以下注释:

使用被取代的软件包:"doSNOW (>= 1.0.19)">

改变这一点似乎并不像预期的那样简单。如果只有registerDoSNOWregisterDoParallel替换,并且.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 选项。支持的多核选项是第一prescheduleset.seedsilentcores,它们类似于与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)
...

最新更新