5

R で並列パッケージを使用するコードを取得する際に問題が発生しています。R 2.15 を使用しています。

簡単な例を次に示します...次の内容を含む「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) { x@legs})

setGeneric("countAfterChopping",function(x) standardGeneric("countAfterChopping"))
setMethod("countAfterChopping", "Animal", function(x) { x@legs <- x@legs-1; x@legs})

次に、R ターミナルで次のコマンドを実行します。

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

2 つのノードのローカル クラスターを開始します。

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

Animal クラスについてクラスタ ノードに伝えます。

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 への最初の呼び出しは期待どおりに機能しますが、2 番目の呼び出しでは次のエラーが発生します。

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

何が起こっているのですか?parSapply の 2 回目の呼び出しが機能しないのはなぜですか?

4

1 に答える 1

3

だからここに何が起こっているのですか:

クラス "Animal" の S4 オブジェクトの場合、この関数は単純にスロットcountを抽出します。実行していたのがこれだけの場合は、クラスター ノードlegsでファイルを評価したり、ソースを取得したりする必要はありません。animal.R必要な情報はすべて によって渡されparSapplyます。

ただし、countAfterChopping関数はスロットに新しい値を割り当てlegsます。ここから楽しみが始まります。スロット割り当て関数には、引数 を指定した`@<-`への呼び出しが含まれています。これにより、関数の評価がトリガーされ、「クラスの定義を参照して、指定された値がこのスロットに許可されていること」がチェックされます( から)。`slot<-`check = TRUEcheckSlotAssignment?checkSlotAssignment

したがって、この方法でスロットに割り当てる場合、クラス定義を認識している必要があり、S4 クラス「アニマル」はクラスター ノードでは認識されません。これが、解析されたファイルの評価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) { x@legs})

  setGeneric('countAfterChopping',function(x) standardGeneric('countAfterChopping'))
  setMethod('countAfterChopping', signature(x='Animal'),
    function(x) { x@legs <- x@legs-1; x@legs})
"
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
于 2012-05-25T06:22:07.443 に答える