2012-05-24 65 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