2012-05-24 14 views
5

Mam problem z uzyskaniem kodu do pracy z pakietem równoległym w R. Używam R 2.15.R równoległy błąd klasy S4 klastra

Oto uproszczony przykład ... Mam plik 'animal.R', który zawiera następujące elementy:

# animal.R 
setClass("Animal", representation(species = "character", legs = "numeric")) 

##Define some Animal methods 
setGeneric("count",function(x) standardGeneric("count")) 
setMethod("count", "Animal", function(x) { [email protected]}) 

setGeneric("countAfterChopping",function(x) standardGeneric("countAfterChopping")) 
setMethod("countAfterChopping", "Animal", function(x) { [email protected] <- [email protected]; [email protected]}) 

Następnie w moim terminalu R, biegnę:

library(parallel) 
source('animal.R') 

Rozpocznij lokalny klaster dwoma węzłami:

cl <- makeCluster(rep('localhost', 2)) 

Powiedz klastrze węzłów o klasie Zwierząt:

clusterEvalQ(cl, parse('animal.R')) 

Następnie uruchom jakiś kod na klastrze:

# This works 
parSapply(cl, list(daisy, fred), count) 

# This doesn't... 
parSapply(cl, list(daisy, fred), countAfterChopping) 

Zatrzymaj klaster:

stopCluster(cl) 

Pierwsze wywołanie parSapply działa zgodnie z oczekiwaniami, ale druga produkuje ten błąd:

Error in checkForRemoteErrors(val) : 
    2 nodes produced errors; first error: "Animal" is not a defined class 

Jakieś pomysły, co się dzieje? Dlaczego drugie połączenie z PARSapply nie działa?

+0

Kiedy 'parse' animal.R, masz unevaluated ekspresję, więc można użyć' clusterEvalQ (cl, eval (parse ('animal.R '))) 'lub po prostu źródło skryptu. Czy to wystarczy? – BenBarnes

+0

Ach, tak ... to chyba wystarczy. Dziękuję bardzo! – Ash

Odpowiedz

3

Więc oto co się dzieje:

Dla obiektów klasy S4 „zwierzę”, funkcja count prostu wydobywa gniazdo legs. Jeśli to wszystko, co robiłeś, nie musisz oceniać ani pobierać pliku animal.R na swoich węzłach klastra. Wszystkie niezbędne informacje zostaną przekazane przez parSapply.

Jednak funkcja countAfterChopping przypisuje nową wartość do gniazda legs i tutaj zaczyna się zabawa. Funkcja przypisania do gniazda `@<-` zawiera wywołanie `slot<-` z argumentem check = TRUE. To uruchamia ocenę funkcji checkSlotAssignment, która sprawdza "czy podana wartość jest dozwolona dla tego slotu, sprawdzając definicję klasy" (z ?checkSlotAssignment).

W związku z tym definicja klasy musi być znana przy przypisywaniu do gniazda w ten sposób, a klasa S4 "Zwierzę" nie jest znana w węzłach klastra. Właśnie dlatego ocena przeanalizowanego pliku animal.R lub pozyskanie go działa. Jednak wystarczy, że ocenisz pierwszy wiersz pliku, tj. Definiując klasę "Animal" w każdym węźle.

Oto zmniejszona, powtarzalne przykład:

animal.R<-" 
    setClass('Animal', representation(species = 'character', legs = 'numeric')) 

    ##Define some Animal methods 
    setGeneric('count',function(x) standardGeneric('count')) 
    setMethod('count', signature(x='Animal'), function(x) { [email protected]}) 

    setGeneric('countAfterChopping',function(x) standardGeneric('countAfterChopping')) 
    setMethod('countAfterChopping', signature(x='Animal'), 
    function(x) { [email protected] <- [email protected]; [email protected]}) 
" 
library(parallel) 

source(textConnection(animal.R)) 

cl <- makeCluster(rep('localhost', 2)) 

daisy<-new("Animal",legs=2,species="H.sapiens") 
fred<-new("Animal",legs=4,species="C.lupus") 

parSapply(cl, list(daisy, fred), count) 
# [1] 2 4 

clusterExport(cl,"animal.R") # 
clusterEvalQ(cl,eval(parse(textConnection(animal.R),n=1))) 

parSapply(cl, list(daisy, fred), countAfterChopping) 
# [1] 1 3 
+0

Tak, to ma sens, bardzo dziękuję za pomoc! – Ash

Powiązane problemy