Soru R'de “foreach ()” işlevini kullanırken bir ilerleme çubuğu nasıl oluşturulur?


R programında döngüler için sayaç oluşturma hakkında bazı bilgilendirici mesajlar vardır. Ancak, paralelleştirilmiş sürümü "foreach ()" ile kullanırken benzer bir işlevi nasıl yaratırsınız?


33
2018-03-24 18:30


Menşei


Yığın Taşması ile ilgili cevapları nasıl kabul edeceğinizi biliyor musunuz? Eğer değilse, lütfen SSS'yi okuyun ve önceki sorularınızın üzerinden geri dönün. - David Heffernan
Bir örnek var foreach ParallelR bloğunda İşte ve bence okumaya değer :) - Patric


Cevaplar:


Düzenleme: Bir güncelleştirme doSNOW paketine kullanımda güzel bir ilerleme çubuğu görüntülemek oldukça kolay hale geldi %dopar% ve Linux, Windows ve OS X üzerinde çalışıyor

doSNOW şimdi resmi olarak ilerleme çubuklarını destekliyor .options.snow argüman.

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) 

İlerlemeyi takip etmenin başka bir yolu, toplam yineleme sayısını göz önünde bulundurursanız, .verbose = T Bu, iterasyonların bittiği konsola yazdırılacağı için.

Linux ve OS X için önceki çözüm

Ubuntu 14.04 (64 bit) ve OS X (El Capitan) üzerinde, kullanım sırasında bile ilerleme çubuğu görüntülenir. %dopar% eğer içinde makeCluster fonksiyon oufile = "" ayarlandı. Windows altında çalışmıyor gibi görünüyor. Yardım makeCluster:

outfile: Stdout ve stderr bağlantı çıkışını işçilerden yönlendirmek. "" yönlendirme olmadığını gösterir (yalnızca yerel makinede çalışanlar için yararlı olabilir). Varsayılanlar Windows / dev / null ’(Windows’ta‘ nul: ’).

Örnek kod:

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) 

Bu İlerleme çubuğu neye benziyor. Çubuğun her ilerlemesi için yeni bir çubuk basıldığından ve bir çalışanın biraz ilerleme gösterebileceğinden dolayı biraz tuhaf görünüyor çünkü bu durum ilerleme çubuğunun zaman zaman ileri geri gitmesine neden oluyor.


29
2017-10-23 00:52



Önerilen bir iyileştirme (bence bu, ayrı bir cevabı garanti etmemek için fikrinize yeterince yakındır): temel olarak, bir tempfile ile cat her yineleme, sonra yeni satırların sayısını sayıyorum (kullanıyorum wc Linux’ta bulunduğumdan, Windows için başka çözümler var ve bunu ilerleme çubuğunu güncellemek için kullanıyorum. Bu, monoton olarak artması avantajına sahiptir. Dezavantaj, her yinelemede bir dosyayı okumalısınız - bunun ne kadar yavaş olduğundan emin değilsiniz. - MichaelChirico
@MichaelChirico önerisi için teşekkürler, ancak şimdi bunu yapmanın 'resmi' bir yolu var. Cevabı güncelledim. - thie1e
Bunun bir işlev içinde çalışmasını sağlayamıyorum. - Brandon Bertelsen


Bu kod değiştirilmiş bir versiyonudur. doRedis örneğive kullanırken bile bir ilerleme çubuğu yapacak %dopar% paralel arka uç ile:

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

İterasyonların sayısını ve zamanın kombinasyon fonksiyonunu bilmek zorundasınız.


8
2018-06-11 14:52



Hmm, bu garip. Benim fonksiyonum, gerçek hesaplamalar bittikten sonra ilerleme çubuğunu bir çekimde güncellemekte gibi görünüyor ... - Zach
Bu yöntem sadece doRedis arka ucu ile çalışabilir. DoParallel arka uç ile nasıl çalışacağını araştırmam gerekecek. - Zach
DoParallel ile iyi çalışmaz çünkü paralel kümeApplyLB işlevini çağırarak uygulandığından, doParallel yalnızca tüm sonuçların döndürülmesinden sonra birleştirme işlevini çağırır. Bu teknik, yalnızca, doRedis, doMPI, doNWS ve (defunct?) DoSMP gibi, birleştirme işlevini çağıran arka uçlarla iyi çalışır. - Steve Weston
@Steve Weston açıklama için teşekkür ederiz. Bu bana çok şey ifade ediyor, ve şimdi neden işlevimin doRedis üzerinde çalıştığını anlıyorum ama doParallel'i değil. - Zach
Konsolu temizlemeyi deneyebilirsiniz ... test edilmemiş. - 42-


Bu şimdi mümkün parallel paketi. OSX 10.11'de R 3.2.3 ile test edildi, RStudio'nun içinde "PSOCK"tür küme.

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)

Garip bir şekilde, sadece doğru şekilde görüntüler style = 3.


8
2018-02-11 01:27



Windows 10'daki R 3.2.2'nin bu kodla herhangi bir ilerleme çubuğu üretmediği görülüyor ... Bu,> = 3.2.3'e özgü mü? - Iain S
@IainS Daha önce, R sürümüne kıyasla işletim sistemi tutarsızlıklarındaki farkı açıklığa kavuştururdum. - shadowtalker


Başlangıç ​​saatini Sys.time() döngüden önce. Satırları veya sütunları veya toplamı bildiğiniz bir şey üzerinde döngü yapın. Daha sonra, döngü içinde bugüne kadar geçen süreyi hesaplayabilirsiniz (bkz. difftime), tamamlanma yüzdesi, hız ve tahmini süre kaldı. Her işlem bu ilerleme çizgisini message işlevi. Bir çıktı gibi bir şey alacaksın

1/1000 complete @ 1 items/s, ETA: 00:00:45
2/1000 complete @ 1 items/s, ETA: 00:00:44

Açıkçası, döngü emri, bunun ne kadar iyi çalıştığını büyük ölçüde etkileyecektir. Hakkında bilmiyorum foreach fakat multicore'ler mclapply kullanarak iyi sonuçlar elde edersiniz mc.preschedule=FALSEBu, öğelerin önceki öğeler tamamlandıkça tek tek işlemlere ayrıldığı anlamına gelir.


6
2018-03-25 10:34



Bir çeşit global sayaç kullanıyor musunuz, yoksa döngü içinde olan dizine güveniyor musunuz (i)? - C8H10N4O2
@ C8H10N4O2: Dizin üzerinde ilmekledi. İle mclapply ile iyi sonuçlar verir mc.preschedule=FALSEve bazen yanlış, ama genellikle varsayılan (ve genellikle daha hızlı) ile yeterince yakın mc.preschedule=TRUE. - otsaw


Aşağıdaki kod R için güzel bir ilerleme çubuğu üretecektir. her biri için kontrol yapısı. Ayrıca değiştirerek grafiksel ilerleme çubukları ile çalışacaktır. txtProgressBar istenen ilerleme çubuğu nesnesine sahip.

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

Yukarıdaki kod sorunuzu en basit biçimiyle yanıtlarken, yanıtlanması gereken daha iyi ve daha zor bir soru,% dopar% ile paralelleştirildiğinde bir foreach ifadesinin ilerlemesini izleyen bir R ilerleme çubuğu oluşturup oluşturamayacağınızdır. Maalesef, paralelleştirilmiş bir foreachun ilerlemesini bu şekilde izlemek mümkün olduğunu düşünmüyorum, ama çok yararlı bir özellik olacağından, birisinin yanlış olduğunu kanıtlamasını çok isterim.


0
2018-05-29 20:04



Bu cevap, paralelleştirme ile ilgili OP sorusunu ele almıyor,% dopar% - ctbrown


Bu kod, paralelleştirilmiş bir izleme çubuğu uygular. foreach kullanarak döngü doMC backend ve mükemmel kullanarak ilerleme paketlemek R. Tarafından belirtilen tüm çekirdeklerin olduğunu varsayar numCores, yaklaşık olarak eşit miktarda iş yapın.

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
2017-07-01 12:34



Aslında birden fazla çekirdek kaydederseniz, bu işe yaramıyor. - luke.sonnet
Yukarıdaki örnek MacBook Pro 2017, R v 3.5.1'de olduğu gibi çalışmaktadır. Yukarıdaki parellelizmle ilgili paketlerden birinin, döngü içindeki asıl işin çok küçük olması halinde birden çok çekirdeğin tekmelemesini önlediğine inanıyorum. Döngü içinde daha zahmetli bir şey koymayı deneyin. Çalışmalı. - marital_weeping
Ama yukarıdakiler çekirdekleri bile kaydetmiyor mu? Bence aslında görevlerin yerini tutmuyor. Yukarıdaki işleri benim için açıklığa kavuşturmak için, ancak aslında birden çok işçiyi kaydettiğimde, yalnızca tamamlanmış izleyiciyi geri gönderir. % dopar% çağrısından önce registerDoMC (2) eklemeyi deneyin. - luke.sonnet
@ luke.sonnet, eksik çizgiyi işaretlediğiniz için teşekkürler. Dahil sonra registerDoMC(cores=numCores), Mac'imde Activity Monitor'e baktığımda birden çok çekirdek çıkıyor. Sana bir fikir vermek için progress [====>-----------------------------] 15% eta: 12sArada gördüğüm şey. - marital_weeping