2012-05-24 11 views
5

Tengo un problema para conseguir que funcione un código con el paquete paralelo en R. Estoy usando R 2.15.R error de cluster de clase S4 paralelo

Aquí hay un ejemplo simplificado ... Tengo un archivo 'animal.R', que contiene lo siguiente:

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

Luego, en mi terminal R, corro:

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

de inicio un grupo local de los dos nodos:

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

Diga a los nodos del clúster acerca de la clase de animales:

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

entonces ejecutar algún código en el clúster:

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

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

Detener el clúster:

stopCluster(cl) 

La primera llamada a parSapply funciona como se esperaba, pero el segundo produce este error:

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

¿Alguna idea de lo que está pasando? ¿Por qué no funciona la segunda llamada a parSapply?

+0

Cuando 'parse' animal.R, se obtiene una expresión sin evaluar, por lo que podría o bien usar' clusterEvalQ (cl, eval (análisis sintáctico ('animal.R '))) 'o solo fuente el script. ¿Eso hizo el truco? – BenBarnes

+0

Ah, sí ... eso parece hacer el truco. ¡Muchas gracias! – Ash

Respuesta

3

Así que aquí es lo que está pasando:

Para los objetos de la clase S4 "Animal", la función count simplemente extrae la ranura legs. Si esto fuera todo lo que estaba haciendo, no necesitaría evaluar ni buscar el archivo animal.R en los nodos de su clúster. Toda la información necesaria se aprobará por parSapply.

Sin embargo, la función countAfterChopping asigna un nuevo valor a la ranura legs, y aquí es donde comienza la diversión. La función de asignación de ranura `@<-` contiene una llamada al `slot<-` con el argumento check = TRUE. Esto desencadena una evaluación de la función checkSlotAssignment, que comprueba "que el valor proporcionado está permitido para este intervalo, consultando la definición de la clase" (de ?checkSlotAssignment).

Por lo tanto, la definición de clase debe conocerse cuando se asigna a una ranura de esta manera, y la clase S4 "Animal" no se conoce en los nodos del clúster. Esta es la razón por la cual evaluar el archivo analizado animal.R o buscarlo funciona. Sin embargo, estarás bien evaluando la primera línea del archivo, es decir, definiendo la clase "Animal" en cada nodo.

Aquí hay una reducción, reproducible ejemplo:

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í, eso tiene sentido, ¡muchas gracias por su ayuda! – Ash

Cuestiones relacionadas