web-dev-qa-db-ja.com

foreachでRcpp関数を実行できません-「シンボルアドレスとして渡されたNULL値」

最初に、RcppパッケージビネットであるWriting R Extensionsを読み、Rcpp.package.skeleton()からパッケージを作成したとしましょう。

パッケージをビルドしてから、関数multiGenerateCSVrow()を追加し、RCMDビルド/ RCMDインストールの前にパッケージディレクトリでcompileAttributes()を実行しました。パッケージをロードした後、関数を直接実行するか、foreach()を介して%do%メソッドを使用して実行できます。

ただし、並行して実行しようとすると、エラーが発生します。

cl <- makePSOCKcluster(8)                                                                                     
registerDoParallel(cl)                                                                                        
rows <- foreach(i=1:8,.combine=rbind,.packages="myPackage") %dopar% multiGenerateCSVrow(scoreMatrix=NIsample,   
                                                                   validMatrix = matrix(1,nrow=10,ncol=10),   
                                                                   cutoffVector = rep(0,10),                  
                                                                   factorVector = randomsCutPlus1[i,],        
                                                                   actualVector = rep(1,10),                  
                                                                   scaleSample = 1)                           
stopCluster(cl)                                                                                               
~                                                                                                             

Error in multiGenerateCSVrow(scoreMatrix = NIsample, validMatrix = matrix(1,  : 
  task 1 failed - "NULL value passed as symbol address"

パッケージNAMESPACEは次のとおりです。

# Generated by roxygen2 (4.0.1): do not edit by hand 
useDynLib(myPackage)                                   
exportPattern("^[[:alpha:]]+")                       
importFrom(Rcpp, evalCpp) 

RcppExports.cppの関連するチャンクは次のとおりです。

// multiGenerateCSVrow
SEXP multiGenerateCSVrow(SEXP scoreMatrix, SEXP validMatrix, SEXP cutoffVector, SEXP factorVector, SEXP actualVector, SEXP scaleSample);
RcppExport SEXP myPackage_multiGenerateCSVrow(SEXP scoreMatrixSEXP, SEXP validMatrixSEXP, SEXP cutoffVectorSEXP, SEXP factorVectorSEXP, SEXP actualVectorSEXP, SEXP scaleSampleSEXP) {
BEGIN_RCPP
    SEXP __sexp_result;
    {
        Rcpp::RNGScope __rngScope;
        Rcpp::traits::input_parameter< SEXP >::type scoreMatrix(scoreMatrixSEXP );
        Rcpp::traits::input_parameter< SEXP >::type validMatrix(validMatrixSEXP );
        Rcpp::traits::input_parameter< SEXP >::type cutoffVector(cutoffVectorSEXP );
        Rcpp::traits::input_parameter< SEXP >::type factorVector(factorVectorSEXP );
        Rcpp::traits::input_parameter< SEXP >::type actualVector(actualVectorSEXP );
        Rcpp::traits::input_parameter< SEXP >::type scaleSample(scaleSampleSEXP );
        SEXP __result = multiGenerateCSVrow(scoreMatrix, validMatrix, cutoffVector, factorVector, actualVector, scaleSample);
        PROTECT(__sexp_result = Rcpp::wrap(__result));
    }
    UNPROTECT(1);
    return __sexp_result;
END_RCPP
}

そしてRcppExports.R:

multiGenerateCSVrow <- function(scoreMatrix, validMatrix, cutoffVector, factorVector, actualVector, scaleSample) {
    .Call('myPackage_multiGenerateCSVrow', PACKAGE = 'myPackage', scoreMatrix, validMatrix, cutoffVector, factorVector, actualVector, scaleSample)
}   

何を探しているのでしょうか?

23

同様の問題があり、.noexport = c(<Functions that were implemented in C++>)foreachに追加することで解決しました。

これらの関数は、グローバル環境から並列コンテキストにインポートされると思いますが、通常の関数ではないため、実際には機能しません。これは、関数を各ノードに個別にロードする必要があることを意味します。私の場合、それはC++コードを含むさまざまなファイルをソースとするSNOWclusterCall()呼び出しでした。

12
henine

Rcppを使用する関数がforeach内で機能しないという問題もありました。 Patrick McCarthyが提案したように、関数をパッケージに入れ、パッケージをインストールしてロードし、forearch with .packages =( "...")で渡しました。

それでもエラーが発生しましたが、関連するすべてのパッケージを更新した後、問題は解決しました。

(コメントしたと思いますが、評判が良くないので、一部の人には役立つかもしれないと思いました)

7
jmb

@ henineと@jmbからの回答に触発されて、「reverse」オプションを試しました。これは、foreachループ内のRccp関数を使用してRファイルを実際にソースし、foreachの.packagesオプションに「Rccp」を含めるようにすることです。 。最も効率的ではないかもしれませんが、仕事をし、簡単です。

何かのようなもの:

cl = makeCluster(n_cores, outfile="")
registerDoParallel(cl)

foreach(n = 1:N,.packages = "Rcpp",.noexport = "<name of Rccp function>")%dopar%{
  source("Scripts/Rccp_functions.R")
  ### do stuff with functions scripted in Rccp_functions.R
}

stopImplicitCluster()

そして@jmbと同様に、私はコメントしたでしょうが、十分な評判がありません:D

2
LaSy