1

Snowfall ライブラリとその使用法について頭を悩ませようとしています。

環境を利用するシミュレーションを書いていると、次の問題が発生しました。並列モード内で関数をロードするためにファイルをソースすると、関数は、並列モード内で関数を直接宣言したときとは異なる環境を使用しているように見えます。

もう少しわかりやすくするために、次の 2 つのスクリプトについて考えてみましょう。

q_func.Rは関数を宣言します

foo.bar <- function(x, envname) assign("val", x, envir = get(envname))
# assigns the value x to the variable "val" in the environment envname

q_snowfall.R降雪を利用したメイン関数

library(snowfall)
SnowFunc <- function(envname) {
    # load the functions

    # Option 1 not working
    source("q_func.R")
    # Option 2 working...
    # foo.bar <- function(x, envname) assign("val", x, envir = get(envname))


    # create the new environment
    assign(envname, new.env())

    # use the function as declared in q_func.R 
    # to assign random numbers to the new env
    foo.bar(x = rnorm(1), envname = envname)

    # return the environment including the random values
    return(get("val", envir = get(envname)))
}

sfInit(parallel = TRUE, cpus = 2)
# create environment 'a' and 'b' that each will get a new variable 
# called 'val' that gets assigned a random value

envs <- c("a", "b")
result <- sfClusterApplyLB(envs, SnowFunc)
sfStop()

スクリプト「q_snowfall.R」を実行すると、エラーが発生します

Error in checkForRemoteErrors(val) : 
  2 nodes produced errors; first error: object 'a' not found

ただし、2 番目のオプション (SnowFunc 関数内で関数を宣言する) を使用すると、エラーは消えます。

Snowfall がさまざまな環境をどのように処理するか知っていますか? または、問題の解決策さえありますか。(「q_func.R」は実際には約 100 行のコードを必要とすることに注意してください。したがって、別のファイルに保存することをお勧めします。したがって、「オプション 2 を保持する」は解決策ではありません!)

どうもありがとうございました!

編集 すべてを変更するget(envname)get(envname, envir = globalenv())、うまくいくようです。しかし、これは多かれ少なかれ回避策であり、降雪のような解決策ではないように思えます。

4

1 に答える 1

1

snowfall問題は、環境を名前で (文字として) 渡しているという事実ではないと思います。のすべての出現を変更する必要はありません。getまた、それを調べるglobalEnvことは実際には安全ではない可能性があります。

getcall infoo.barを代わりに look in parent.frame()(つまり、呼び出された環境)に変更するだけで十分foo.barです。以下は私のマシンで機能しました。

新しいq_func.R

foo.bar <- function(x, envname) assign("val", x, envir=get(envname,
                                pos=parent.frame()))

(そうではない) new q_snowfall.R

library(snowfall)
SnowFunc <- function(envname) {

    assign(envname, new.env())
    foo.bar(x = rnorm(1), envname = envname)

    return(get("val", envir = get(envname)))
}

source("q_func.R")
sfInit(parallel = TRUE, cpus = 2)
sfExport("foo.bar")

envs <- c("a", "b")
result <- sfClusterApplyLB(envs, SnowFunc)
sfStop()

sourceまた、クラスターを開始する前に、各ノードsfExportにエクスポートしていたことにも注意してください。foo.bar

于 2015-07-26T11:38:18.803 に答える