Comment créer une barre de progression en utilisant la fonction "foreach()" dans R?

il y a quelques messages informatifs sur la façon de créer un compteur pour les boucles dans un programme R. Cependant, comment créer une fonction similaire en utilisant la version parallélisée avec "foreach()"?

33
demandé sur Andrie 2011-03-24 21:30:49

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.

30
répondu thie1e 2016-08-11 17:54:58

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.

8
répondu Zach 2015-01-31 21:33:26

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.

8
répondu shadowtalker 2017-04-04 13:36:01

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 multicoremclapply 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.

6
répondu otsaw 2011-03-25 10:34:18

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)
}
0
répondu marital_weeping 2018-08-06 06:46:01

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é.

-1
répondu Nixuz 2011-05-29 20:04:49