11

ここで、Dirk Eddelbuettel のRcppチュートリアルに取り組んでいます。

http://www.rinfinance.com/agenda/

C++ ファイルをディレクトリに保存し、それを呼び出して R 内から実行する方法を学びました。私が実行している C++ ファイルは「logabs2.ccp」と呼ばれ、その内容は Dirk のスライドの 1 つから直接引用されています。

#include <Rcpp.h>

using namespace Rcpp;

inline double f(double x) { return ::log(::fabs(x)); }

// [[Rcpp::export]]
std::vector<double> logabs2(std::vector<double> x) {
    std::transform(x.begin(), x.end(), x.begin(), f);
    return x;
}

このRコードで実行します:

library(Rcpp)
sourceCpp("c:/users/mmiller21/simple r programs/logabs2.cpp")
logabs2(seq(-5, 5, by=2))
# [1] 1.609438 1.098612 0.000000 0.000000 1.098612 1.609438

デフォルトでインストールされるように見えるR GUI内からWindows 7マシンでコードを実行しています。の最新バージョンもインストールしましたRtools。上記の R コードは、実行に比較的時間がかかるようです。その時間のほとんどは C++ コードのコンパイルに費やされており、C++ コードがコンパイルされると非常に速く実行されると思います。 確かに、計算時間が短縮さMicrobenchmarkれることを示唆しています。Rcpp

これまで C++ を使用したことはありませんが、C コードをコンパイルすると *.exe ファイルが生成されることは知っています。というファイルからハードドライブを検索しましlogabs2.exeたが、見つかりません。logabs2.exeファイルが作成された場合、上記の C++ コードがさらに高速に実行されるかどうか疑問に思っています。ファイルを作成してlogabs2.exeどこかのフォルダーに保存し、それを使用したいときにいつでも Rcpp にそのファイルを呼び出させることはできますか? それが理にかなっているのかどうかはわかりません。C++ 関数を *.exe ファイルに格納できれば、Rcpp で使用するたびに関数をコンパイルする必要がなくなり、Rcpp コードはさらに高速になるでしょう。

この質問が意味をなさないか、重複している場合は申し訳ありません。C++ 関数を *.exe ファイルとして保存できる場合は、上記の R コードを変更して実行する方法を誰かが教えてくれることを願っています。これについて助けてくれてありがとう、または私が提案することが不可能または推奨されない理由を正直に教えてくれてありがとう.

Dirk の新しい本を見るのを楽しみにしています。

4

3 に答える 3

6

user1981275、Dirk Eddelbuettel、Romain Francois の回答に感謝します。以下は、C++ ファイルをコンパイルして *.dll を作成し、.dll 内でその *.dll ファイルを呼び出して使用する方法ですR

ステップ 1. 「c:\users\mmiller21\myrpackages」という名前の新しいフォルダーを作成し、「logabs2.cpp」ファイルをその新しいフォルダーに貼り付けました。ファイル「logabs2.cpp」は、私の元の投稿で説明したように作成されました。

ステップ 2. 新しいフォルダー内に、作成した「新しいパッケージの作成.r」というファイルをR使用して、「logabs2」という名前の新しいパッケージを作成しました。R「新しいパッケージ作成.r」の内容は次のとおりです。

setwd('c:/users/mmiller21/myrpackages/')

library(Rcpp)

Rcpp.package.skeleton("logabs2", example_code = FALSE, cpp_files = c("logabs2.cpp"))

Rcpp.package.skeletonHadley Wickham の Web サイトの 1 つで 上記の構文を見つけました: https://github.com/hadley/devtools/wiki/Rcpp

ステップ 3. DOS コマンド ウィンドウで次の行を使用して、新しいRパッケージ「logabs2」をインストールしました。R

C:\Program Files\R\R-3.0.1\bin\x64>R CMD INSTALL -l c:\users\mmiller21\documents\r\win-library\3.0\ c:\users\mmiller21\myrpackages\logabs2

どこ:

rcmd.exe ファイルの場所は次のとおりです。

C:\Program Files\R\R-3.0.1\bin\x64>

R私のコンピューターにインストールされているパッケージの場所は次のとおりです。

c:\users\mmiller21\documents\r\win-library\3.0\

Rインストール前の新しいパッケージの場所は次のとおりです。

c:\users\mmiller21\myrpackages\

DOS コマンド ウィンドウで使用される構文は、試行錯誤によって発見されたものであり、理想的ではない可能性があります。ある時点で、'logabs2.cpp' のコピーを 'C:\Program Files\R\R-3.0.1\bin\x64>' に貼り付けましたが、それは問題ではないと思います。

ステップ 4. 新しいRパッケージをインストールした後、「c:/users/mmiller21/myrpackages/」フォルダーにある「new package usage.r」という名前のファイルを使用してR実行しました (フォルダーは重要ではないと思いますが)。「新しいパッケージの使用法.r」の内容は次のとおりです。

library(logabs2)
logabs2(seq(-5, 5, by=2))

出力は次のとおりです。

# [1] 1.609438 1.098612 0.000000 0.000000 1.098612 1.609438

このファイルは、Rcpp私に尋ねることなくパッケージをロードしました。

この場合R、これを正しく行ったと仮定すると、base の方が高速でした。

#> microbenchmark(logabs2(seq(-5, 5, by=2)), times = 100)
#Unit: microseconds
#                        expr    min     lq  median     uq     max neval
# logabs2(seq(-5, 5, by = 2)) 43.086 44.453 50.6075 69.756 190.803   100

#> microbenchmark(log(abs(seq(-5, 5, by=2))), times=100)
#Unit: microseconds
#                         expr    min     lq median    uq     max neval
# log(abs(seq(-5, 5, by = 2))) 38.298 38.982 39.666 40.35 173.023   100

ただし、dll ファイルを使用すると、外部の cpp ファイルを呼び出すよりも高速でした。

system.time(

cppFunction("
NumericVector logabs(NumericVector x) {
    return log(abs(x));
}
")

)

#   user  system elapsed 
#   0.06    0.08    5.85 

この場合、base R は *.dll ファイルよりも高速または同程度に高速に見えますが、ほとんどの場合 、*.dll ファイルを使用Rcppすると base よりも高速になることに疑いの余地はありません。R

これは、R パッケージを作成したり、Rcpp を使用したりする私の最初の試みであり、間違いなく最も効率的な方法を使用していませんでした。また、本文中に誤字脱字がありましたことをお詫び申し上げます。

編集

以下のコメントで、Romain Francois が *.cpp ファイルを次のように変更することを提案したと思います。

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]

NumericVector logabs(NumericVector x) {
return log(abs(x));
}

そして、R今行ったパッケージを再作成します。R次に、次のコードを使用してbase と新しいパッケージを比較しました。

library(logabs)

logabs(seq(-5, 5, by=2))
log(abs(seq(-5, 5, by=2)))

library(microbenchmark)

microbenchmark(logabs(seq(-5, 5, by=2)), log(abs(seq(-5, 5, by=2))), times = 100000)

ベースRはまだ少し速いか、違いはありません:

Unit: microseconds
                         expr    min     lq median     uq       max neval
   logabs(seq(-5, 5, by = 2)) 42.401 45.137 46.505 69.073 39754.598 1e+05
 log(abs(seq(-5, 5, by = 2))) 37.614 40.350 41.718 62.234  3422.133 1e+05

おそらくこれは、baseRが既にベクトル化されているためです。より複雑な関数を使用すると、 baseRがはるかに遅くなると思います。あるいは、最も効率的なアプローチをまだ使用していないか、単にどこかでエラーを犯しただけかもしれません。

于 2013-06-18T07:17:04.363 に答える