web-dev-qa-db-ja.com

Rで「foreach()」関数を使用する場合、プログレスバーをどのように作成しますか?

rプログラムでループのカウンターを作成する方法についての有益な投稿があります。しかし、「foreach()」で並列化されたバージョンを使用する場合、同様の関数をどのように作成しますか?

42
exl

編集:doSNOWパッケージへの pdate の後、%dopar%を使用すると、Niceプログレスバーを表示するのが非常に簡単になり、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) 

進行状況を追跡するさらにもう1つの方法は、反復の総数を覚えている場合、.verbose = Tを設定することです。これにより、どの反復が終了したかがコンソールに出力されます。

LinuxおよびOS Xの以前のソリューション

Ubuntu 14.04(64ビット)およびOS X(El Capitan)では、makeCluster関数で%dopar%が設定されている場合、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) 

これ は、進行状況バーの外観です。新しいバーがバーの進行ごとに印刷されるため、およびワーカーが少し遅れてプログレスバーがときどき前後に移動する可能性があるため、少し奇妙に見えます。

43
thie1e

このコードは 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)

事前に、反復数と組み合わせ関数を知っておく必要があります。

9
Zach

これはparallelパッケージで可能になりました。 "PSOCK"タイプのクラスターを使用して、RStudio内で実行されているOSX 10.11上のR 3.2.3でテストされています。

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でのみ正しく表示されます。

8
shadowtalker

ループの前に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を使用して適切な結果が得られます。これは、項目が1つずつプロセスに割り当てられることを意味します1つ前のアイテムが完成した順に並べます。

6
otsaw

これを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) 
5
Dewey Brooke

このコードは、foreachバックエンドを使用し、doMCの優れた progress パッケージを使用して、並列化されたRループを追跡する進行状況バーを実装します。 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)
}
1
marital_weeping