簡體   English   中英

在R中使用“foreach()”函數時如何創建進度條?

[英]How do you create a progress bar when using the “foreach()” function in R?

有關如何在R程序中創建循環計數器的一些信息性帖子。 但是,在使用帶有“foreach()”的並行化版本時,如何創建類似的功能?

編輯: 更新 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)上,如果在makeCluster函數中設置了oufile = ""即使使用%dopar%也會顯示進度條。 它似乎不適用於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) 

就是進度條的樣子。 它看起來有點奇怪,因為每個條形圖都會打印一個新的條形圖,因為工作人員可能會滯后一點,導致進度條偶爾會來回走動。

此代碼是doRedis示例的修改版本,即使將%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)

您必須提前知道迭代次數和組合函數。

現在可以使用parallel包。 在OSX 10.11上使用R 3.2.3進行測試,在RStudio中運行,使用"PSOCK"類型的集群。

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正確顯示。

您可以在循環之前使用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但是使用multicoremclapply你會得到很好的結果使用mc.preschedule=FALSE ,這意味着項目按照先前項目的順序逐個分配給進程。

此代碼使用doMC后端實現跟蹤並行化foreach循環的進度條,並使用R的優秀進度包。 它假定numCores指定的所有核心的numCores大致相等。

library(foreach)
library(doMC)
library(progress)

iterations <- 100
numCores <- 8

registerDoMC(cores=numCores)

pbTracker <- function(pb,i,numCores) {
    if (i %% numCores == 0) {
        pb$tick()
    }
}

pb <- progress_bar$new(
  format <- " progress [:bar] :percent eta: :eta",
  total <- iterations / numCores, clear = FALSE, width= 60)


output = foreach(i=1:iterations) %dopar% {
    pbTracker(pb,i,numCores)
    Sys.sleep(1/20)
}

您也可以使用progress包。

它看起來像什么

# 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) 

以下代碼將在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的進度是不可能的,但我希望有人能證明我錯了,因為這將是非常有用的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM