[英]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
但是使用multicore
的mclapply
你會得到很好的結果使用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.