2012-05-24 14 views
5

Sto riscontrando un problema nel far funzionare il codice con il pacchetto parallelo in R. Sto usando R 2.15.Errore parallelo classe S4 S1

Ecco un esempio semplificato ... Ho un file 'animal.R', che contiene quanto segue:

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

Poi, nel mio terminale R, corro:

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

Inizio un gruppo locale dei due nodi:

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

Dite ai nodi del cluster sulla classe degli animali:

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

Poi eseguire del codice sul cluster:

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

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

arresto del cluster:

stopCluster(cl) 

La prima chiamata a parSapply funziona come previsto, ma il secondo produce questo errore:

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

Qualche idea cosa sta succedendo? Perché la seconda chiamata a parSapply non funziona?

+0

Quando si 'parse' animal.R, si ottiene un'espressione non valutata, così da poter utilizzare sia clusterEvalQ (cl, eval (parse ('animal.R' '))) 'o semplicemente fonte la sceneggiatura. Questo ha fatto il trucco? – BenBarnes

+0

Ah, sì ... sembra che faccia il trucco. Grazie mille! – Ash

risposta

3

Quindi, ecco quello che sta succedendo:

Per gli oggetti della classe S4 "Animal", la funzione count estrae semplicemente slot legs. Se questo fosse tutto ciò che stavi facendo, non sarebbe necessario valutare o creare il file animal.R sui nodi del cluster. Tutte le informazioni necessarie saranno passate da parSapply.

Tuttavia, la funzione countAfterChopping assegna un nuovo valore allo slot legs ed è qui che inizia il divertimento. La funzione di assegnazione degli slot `@<-` contiene una chiamata allo `slot<-` con l'argomento check = TRUE. Ciò innesca una valutazione della funzione checkSlotAssignment, che verifica "che il valore fornito sia consentito per questo slot, consultando la definizione della classe" (da ?checkSlotAssignment).

Pertanto, la definizione della classe deve essere nota durante l'assegnazione a uno slot in questo modo e la classe S4 "Animal" non è nota sui nodi del cluster. Questo è il motivo per cui si valuta il file analizzato animal.R o si esegue il sourcing. Tuttavia, si andrebbe bene solo valutando la prima riga del file, cioè definendo la classe "Animale", su ciascun nodo.

Ecco un ridotto, ad esempio riproducibile:

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

Sì, questo ha senso, grazie mille per il vostro aiuto! – Ash

Problemi correlati