2016-11-24 44 views
5

için bir işlev oluşturma Paralel olarak yapmak istediğim bir işlem var, ancak bazı strange error nedeniyle başarısız oldum. Şimdi, ana CPU'daki arızalı görevi birleştirmeyi ve hesaplamayı düşünüyorum. Ancak, .combin için böyle bir işlevin nasıl yazılacağını bilmiyorum.Foreach

Nasıl yazılmalıdır?

Bunları nasıl yazacağımı biliyorum, örneğin this yanıtı bir örnek sağlar, ancak başarısız olan görevlerle nasıl başa çıkılacağını sağlamaz.

Ancak
foreach(i=1:100, .combine = function(x, y){tryCatch(?)} %dopar% { 
    long_process_which_fails_randomly(i) 
} 

, ben .combine fonksiyonunda bu görevin girişini kullanmak nasıl (bu yapılabilir ise):

ben böyle bir şey yapsın? Veya hesaplamak için bir bayrak veya liste döndürmek için %dopar%'un içine girmem gerekir mi?

cevap

2

Birleştirme işlevindeki görevleri yürütmek için, foreach döngüsünün gövdesi tarafından döndürülen sonuç nesnesine fazladan bilgi eklemeniz gerekir. Bu durumda, bu bir hata bayrağı ve i değeri olacaktır. Bunu yapmanın birçok yolu vardır, ama burada bir örnek:

tüm görevleri bilgisayarlı edilene kadar defalarca paralel döngü yürüterek bu sorunla başa çıkmak için cazip olacaktır

comb <- function(results, x) { 
    i <- x$i 
    result <- x$result 
    if (x$error) { 
    cat(sprintf('master computing failed task %d\n', i)) 
    # Could call function repeatedly until it succeeds, 
    # but that could hang the master 
    result <- try(fails_randomly(i)) 
    } 
    results[i] <- list(result) # guard against a NULL result 
    results 
} 

r <- foreach(i=1:100, .combine='comb', 
      .init=vector('list', 100)) %dopar% { 
    tryCatch({ 
    list(error=FALSE, i=i, result=fails_randomly(i)) 
    }, 
    error=function(e) { 
    list(error=TRUE, i=i, result=e) 
    }) 
} 
:

x <- rnorm(100) 
results <- lapply(x, function(i) simpleError('')) 

# Might want to put a limit on the number of retries 
repeat { 
    ix <- which(sapply(results, function(x) inherits(x, 'error'))) 
    if (length(ix) == 0) 
    break 

    cat(sprintf('computing tasks %s\n', paste(ix, collapse=','))) 
    r <- foreach(i=x[ix], .errorhandling='pass') %dopar% { 
    fails_randomly(i) 
    } 

    results[ix] <- r 
} 

Bu çözümün hatalar meydana geldiğinde çok yararlı olan .errorhandling seçeneğini kullandığını unutmayın. Bu seçenek hakkında daha fazla bilgi için foreach man sayfasına bakın.

+0

Cevabınız için teşekkürler! Tüm görev hesaplanana kadar neden paralel döngüyü tekrarlamaya başladığınızı açıklar mısınız? Bu şekilde daha kolay/hızlı olacağını düşünüyor musunuz, çünkü hata her seferinde farklı yinelemelerde gerçekleşir? – Llopis

+0

@Llopis Her şey kendi özel probleminize bağlıdır. Hata ana sayfada gerçekleşemezse, yaklaşımınız muhtemelen daha iyidir. Usta üzerinde olması muhtemelse o zaman işçileri de kullanabilirsiniz çünkü bu daha hızlı olacaktır. Hataya dayanıklı programların yazılması zor olabilir, bu yüzden bazı farklı yaklaşımları düşünmek yararlı olacaktır. –

+0

Hatanın kaynağını anlamıyorum gibi, tahmin etmek zor, ancak alternatifler için teşekkürler – Llopis