2012-05-24 51 views
5

我有一个问题得到一些代码与R中的并行包一起使用。我使用R 2.15。R并行S4类集群错误

这里有一个简单的例子...我有一个文件 'animal.R',这包含以下内容:

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

然后,在我的R端子,我跑:

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

开始两个节点的本地集群:

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

讲述动物类的群集节点:

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

然后在集群上运行一些代码:

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

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

停止集群:

stopCluster(cl) 

工程按预期parSapply第一个呼叫,但第二个产生这个错误:

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

任何想法发生了什么?为什么第二次调用parSapply不起作用?

+0

当你'parse' animal.R,你会得到一个未计算的表达,所以你既可以使用'clusterEvalQ(CL,EVAL(解析('animal.R ')))'或者只是来源脚本。这是否有诀窍? – BenBarnes

+0

啊,是的......这似乎在伎俩。非常感谢! – Ash

回答

3

所以这里发生了什么:

对于类“动物” S4对象时,count功能只需提取legs插槽。如果这是您所做的全部工作,则无需在群集节点上评估或获取文件animal.R。所有必要的信息将通过parSapply

但是,countAfterChopping函数为legs插槽分配了一个新值,这就是趣味开始的地方。插槽分配功能`@<-`包含对参数check = TRUE`slot<-`的调用。这会触发功能checkSlotAssignment的评估,该功能通过查阅该类别的定义(从?checkSlotAssignment)检查“提供的值是否允许用于该插槽”。

因此,在以这种方式分配到插槽时必须知道类定义,并且在集群节点上未知S4类“Animal”。这就是为什么评估解析文件animal.R或采购它的原因。但是,只需评估文件的第一行,即在每个节点上定义类“Animal”即可。

这里有一个降低,可重复的例子:

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

是的,这很有道理,非常感谢您的帮助! – Ash