在R中使用“foreach()”函数时如何创建进度条?

时间:2011-03-24 18:30:50

标签: r foreach progress-bar

有一些关于如何在R程序中为循环创建计数器的信息性帖子。但是,如何在使用带有“foreach()”的并行化版本时创建类似的功能?

7 个答案:

答案 0 :(得分:36)

编辑:在update到doSNOW包之后,使用%dopar%显示一个好的进度条变得非常简单,它适用于Linux,Windows和OS X

doSNOW现在通过.options.snow参数正式支持进度条。

library(doSNOW)
cl <- makeCluster(2)
registerDoSNOW(cl)
iterations <- 100
pb <- txtProgressBar(max = iterations, style = 3)
progress <- function(n) setTxtProgressBar(pb, n)
opts <- list(progress = progress)
result <- foreach(i = 1:iterations, .combine = rbind, 
                  .options.snow = opts) %dopar%
{
    s <- summary(rnorm(1e6))[3]
    return(s)
}
close(pb)
stopCluster(cl) 

另一种跟踪进度的方法,如果你记住迭代的总数,就是设置.verbose = T,因为这将打印到控制台,迭代已经完成。

以前的Linux和OS X解决方案

在Ubuntu 14.04(64位)和OS X(El Capitan)上,如果设置了%dopar%功能makeCluster,即使使用oufile = "",也会显示进度条。它似乎不适用于Windows。来自makeCluster的帮助:

outfile:从工作者那里引导stdout和stderr连接输出的位置。 “”表示没有重定向(这可能仅对本地计算机上的工作人员有用)。默认为'/ dev / null'(Windows上为'nul:')。

示例代码:

library(foreach)
library(doSNOW)
cl <- makeCluster(4, outfile="") # number of cores. Notice 'outfile'
registerDoSNOW(cl)
iterations <- 100
pb <- txtProgressBar(min = 1, max = iterations, style = 3)
result <- foreach(i = 1:iterations, .combine = rbind) %dopar% 
{
      s <- summary(rnorm(1e6))[3]
      setTxtProgressBar(pb, i) 
      return(s)
}
close(pb)
stopCluster(cl) 

This是进度条的样子。它看起来有点奇怪,因为每个条形图都会打印一个新的条形图,因为工作人员可能会滞后一点,导致进度条偶尔会来回走动。

答案 1 :(得分:8)

此代码是doRedis example的修改版本,即使将%dopar%与并行后端一起使用,也会生成进度条:

#Load Libraries
library(foreach)
library(utils)
library(iterators)
library(doParallel)
library(snow)

#Choose number of iterations
n <- 1000

#Progress combine function
f <- function(){
  pb <- txtProgressBar(min=1, max=n-1,style=3)
  count <- 0
  function(...) {
    count <<- count + length(list(...)) - 1
    setTxtProgressBar(pb,count)
    Sys.sleep(0.01)
    flush.console()
    c(...)
  }
}

#Start a cluster
cl <- makeCluster(4, type='SOCK')
registerDoParallel(cl)

# Run the loop in parallel
k <- foreach(i = icount(n), .final=sum, .combine=f()) %dopar% {
  log2(i)
}

head(k)

#Stop the cluster
stopCluster(cl)

您必须提前知道迭代次数和组合函数。

答案 2 :(得分:8)

现在可以使用parallel包。在OSX 10.11上使用R 3.2.3进行测试,使用"PSOCK"类型的集群在RStudio内运行。

library(doParallel)

# default cluster type on my machine is "PSOCK", YMMV with other types
cl <- parallel::makeCluster(4, outfile = "")
registerDoParallel(cl)

n <- 10000
pb <- txtProgressBar(0, n, style = 2)

invisible(foreach(i = icount(n)) %dopar% {
    setTxtProgressBar(pb, i)
})

stopCluster(cl)

奇怪的是,它只能与style = 3正确显示。

答案 3 :(得分:6)

在循环之前用Sys.time()保存开始时间。循环遍历行或列或您知道总数的内容。然后,在循环内部,您可以计算到目前为止的时间(参见difftime),完成百分比,速度和估计剩余时间。每个进程都可以使用message函数打印这些进度行。你会得到类似

的输出
1/1000 complete @ 1 items/s, ETA: 00:00:45
2/1000 complete @ 1 items/s, ETA: 00:00:44

显然,循环顺序将极大地影响其工作效果。不知道foreach但使用multicore mclapply使用mc.preschedule=FALSE可以获得良好的结果,这意味着项目会逐个分配给流程按照以前的项目完成。

答案 4 :(得分:1)

此代码实现了一个进度条,该进度条使用read_csv后端并使用foreach中出色的progress包来跟踪并行化的doMC循环。假设R指定的所有核心所做的工作量大致相等。

numCores

答案 5 :(得分:0)

您也可以将其与progress软件包一起使用。

what it looks like

# loading parallel and doSNOW package and creating cluster ----------------
library(parallel)
library(doSNOW)

numCores<-detectCores()
cl <- makeCluster(numCores)
registerDoSNOW(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.snow = opts) %dopar% {
  summary(rnorm(1e6))[3]
}

stopCluster(cl) 

答案 6 :(得分:-1)

以下代码将在R中为foreach控件结构生成一个很好的进度条。通过将txtProgressBar替换为所需的进度条对象,它也可以使用图形进度条。

# Gives us the foreach control structure.
library(foreach)
# Gives us the progress bar object.
library(utils)
# Some number of iterations to process.
n <- 10000
# Create the progress bar.
pb <- txtProgressBar(min = 1, max = n, style=3)
# The foreach loop we are monitoring. This foreach loop will log2 all 
# the values from 1 to n and then sum the result. 
k <- foreach(i = icount(n), .final=sum, .combine=c) %do% {
    setTxtProgressBar(pb, i)
    log2(i)
}
# Close the progress bar.
close(pb)

虽然上面的代码以最基本的形式回答了你的问题,但是更好和更难回答的问题是你是否可以创建一个R进度条来监视foreach语句与%dopar%并行化时的进度。不幸的是,我不认为以这种方式监视并行化foreach的进度是可能的,但我希望有人能证明我是错的,因为这将是非常有用的功能。