40

ここで関連する質問をしたところ、応答はうまくいきました: 並列の parLapply を使用: 並列コード内の変数にアクセスできません

問題は、関数内で答えを使用しようとすると、のデフォルト環境にあると思われるため、機能しないことですclusterExport。私はビネットを読んでヘルプファイルを見ましたが、非常に限られた知識ベースでこれに取り組んでいます. 私が使用した方法は、次のようparLapplyに動作することを期待していましlapplyたが、そうではないようです。

これが私の試みです:

par.test <- function(text.var, gc.rate=10){ 
    ntv <- length(text.var)
    require(parallel)
    pos <-  function(i) {
        paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
    }
    cl <- makeCluster(mc <- getOption("cl.cores", 4))
    clusterExport(cl=cl, varlist=c("text.var", "ntv", "gc.rate", "pos"))
    parLapply(cl, seq_len(ntv), function(i) {
            x <- pos(text.var[i])
            if (i%%gc.rate==0) gc()
            return(x)
        }
    )
}

par.test(rep("I like cake and ice cream so much!", 20))

#gives this error message
> par.test(rep("I like cake and ice cream so much!", 20))
Error in get(name, envir = envir) : object 'text.var' not found
4

2 に答える 2

52

デフォルトでは、 は、 で指定されたエクスポートするオブジェクトをclusterExport検索します。オブジェクトが にない場合は、それらのオブジェクトを見つけることができる環境を 指定する必要があります。.GlobalEnvvarlist.GlobalEnvclusterExport

あなたはあなたclusterExportを次のように変更することができます(私はテストしていませんが、コメントで動作すると言いました)

clusterExport(cl=cl, varlist=c("text.var", "ntv", "gc.rate", "pos"), envir=environment())

このようにして、エクスポートするオブジェクトの関数の環境を調べます。

于 2012-08-19T01:09:48.613 に答える
18

もう 1 つの解決策は、追加の変数を関数の引数として含めることです。parLapply もそれらをエクスポートします。'text.var' がビッグ データである場合、オブジェクト全体ではなく、各ワーカーに関連する text.var の部分のみがエクスポートされるため、インデックスではなく、適用される引数にすることをお勧めします。各労働者に。

par.test <- function(text.var, gc.rate=10){ 
    require(parallel)
    pos <-  function(i) {
        paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
    }
    cl <- makeCluster(mc <- getOption("cl.cores", 4))
    parLapply(cl, text.var, function(text.vari, gc.rate, pos) {
        x <- pos(text.vari)
        if (i%%gc.rate==0) gc()
        x
    }, gc.rate, pos)
}

これもコンセプトとしては嬉しい。(ガベージ コレクターを明示的に呼び出す必要はほとんどありません)。

source()スクリプトを実行するときのメモリ管理は、追加の問題を引き起こします。比較

> stop("oops")
Error: oops
> traceback()
1: stop("oops")

スクリプトで同じ呼び出しを使用

> source("foo.R")
Error in eval(ei, envir) : oops
> traceback()
5: stop("oops") at foo.R#1
4: eval(ei, envir)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("foo.R")

serialize()データをワーカーに移動するために内部的に使用されるR の関数はparLapply()、.GlobalEnv まですべてをシリアル化することを思い出してください。そのため、スクリプトで作成されたデータ オブジェクトはワーカーにシリアル化されますが、対話的に実行された場合はシリアル化されません。これは、スクリプト実行時の @SeldeomSeenSlim の問題の原因となる可能性があります。おそらく解決策は、「データ」を「アルゴリズム」からより明確に分離することです。たとえば、ファイル システムやデータベースを使用するか、オブジェクトを格納するために ... を使用します。

于 2012-08-19T05:33:04.163 に答える