Comment créer une barre de progression en utilisant la fonction "foreach()" dans R?
6 réponses
modifier: après un mise à jour pour le paquet doSNOW, il est devenu assez simple d'afficher une barre de progression agréable en utilisant %dopar%
et il fonctionne sur Linux, Windows et OS X
doSNOW
supporte maintenant officiellement les barres de progression via le.options.snow
argument.
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)
une autre façon de suivre les progrès, si vous gardez à l'esprit le nombre total d'itérations, est de définir .verbose = T
comme ceci imprimera à la console quelles itérations ont été fini.
solution précédente Pour Linux et OS X
sur Ubuntu 14.04 (64 bit) et OS X (El Capitan) la barre de progression est affichée même en utilisant %dopar%
si le makeCluster
function oufile = ""
est réglé. Il ne semble pas fonctionner sous Windows. De l'aide sur les makeCluster
:
outfile: où diriger la sortie de connexion stdout et stderr des travailleurs. ""indique aucune redirection (qui ne peut être utile que pour les travailleurs sur la machine locale). Par défaut à ' /dev / null’ ('null:' sous Windows).
exemple de code:
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)
est à quoi ressemble la barre de progression. Il semble un peu bizarre depuis qu'une nouvelle barre est imprimée pour chaque progression de la barre et parce qu'un travailleur peut être un peu en retard ce qui provoque la barre de progression de va-et-vient de temps en temps.
ce code est une version modifiée du doRedis example, et fera une barre de progression même en utilisant %dopar%
en parallèle avec une backend:
#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)
Vous devez connaître le nombre d'itérations et la fonction de combinaison à l'avance.
C'est maintenant possible avec le parallel
paquet. Testé avec R 3.2.3 sur OSX 10.11, tournant à L'intérieur de RStudio, en utilisant un "PSOCK"
de type cluster.
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)
Étrangement, il ne s'affiche correctement avec style = 3
.
vous économisez l'Heure de début avec Sys.time()
avant la boucle. Boucle sur des lignes ou des colonnes ou quelque chose que vous connaissez le total de. Puis, à l'intérieur de la boucle, vous pouvez calculer le temps passé jusqu'ici (voir difftime
), pourcentage terminé, vitesse et temps estimé laissé. Chaque processus peut imprimer ces progrès lignes avec le message
fonction. Vous obtiendrez une sortie quelque chose comme
1/1000 complete @ 1 items/s, ETA: 00:00:45
2/1000 complete @ 1 items/s, ETA: 00:00:44
évidemment, l'ordre de bouclage aura une grande influence sur la façon dont cela fonctionne. Ne sais pas à propos de foreach
mais avec multicore
mclapply
vous obtiendrez de bons résultats en utilisant mc.preschedule=FALSE
, ce qui signifie que les items sont alloués aux processus un par un dans l'ordre où les items précédents sont complétés.
ce code implémente une barre de progression en traçant un foreach
boucle en utilisant le doMC
backend, et l'aide de l'excellent cours package R
. Il suppose que tous les noyaux, spécifiés par numCores
, environ la même quantité de travail.
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)
}
le code suivant produira une belle barre de progression en R pour le foreach structure de contrôle. Il fonctionnera également avec les barres de progression graphiques en remplaçant txtProgressBar avec l'objet de barre de progression désiré.
# 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)
alors que le code ci-dessus répond à votre question dans sa forme la plus basique une question meilleure et beaucoup plus difficile à répondre est de savoir si vous pouvez créer une barre de progression R qui surveille la progression d'un énoncé de foreach quand il est parallélisé avec %dopar%. Malheureusement, je ne pense pas qu'il est possible de suivre l'avancement d'un parallélisée foreach de cette façon, mais j'aimerais que quelqu'un me prouver le contraire, qu'il serait très utile de fonctionnalité.