web-dev-qa-db-ja.com

関数内でのparLapplyおよびclusterExportの使用

ここで関連する質問をしましたが、応答はうまくいきました: parallelの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
34
Tyler Rinker

デフォルトでは、clusterExportは、varlistで名前が付けられているエクスポートするオブジェクトを.GlobalEnvで探します。オブジェクトが.GlobalEnvにない場合は、clusterExportに、それらのオブジェクトを検出できる環境を通知する必要があります。

clusterExportを次のように変更できます(私はテストしていませんが、コメントで機能すると言っています)

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

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

43
GSee

別の解決策は、関数の引数として追加の変数を含めることです。 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() ingするときのメモリ管理により、さらに問題が発生します。比較する

_> 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の問題の原因となる場合があります。おそらく解決策は、「データ」と「アルゴリズム」をより明確に分離することです。たとえば、ファイルシステムやデータベースを使用したり、オブジェクトを保存したりします。

16
Martin Morgan