使用Rcpp运行已编译的C++代码

Mar*_*ler 9 c++ r rcpp

我一直在努力通过Dirk Eddelbuettel的Rcpp教程:

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

我已经学会了如何在目录中保存C++文件并调用它并从R中运行它.我运行的C++文件名为'logabs2.ccp',其内容直接来自Dirk的幻灯片之一:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我用这个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
Run Code Online (Sandbox Code Playgroud)

我在R GUI中运行Windows 7计算机上的代码,默认情况下似乎是安装的.我还安装了最新版本的Rtools.上面的R代码似乎需要相对较长的时间才能运行.我怀疑大部分时间都用于编译C++代码,而且一旦编译C++代码,它就会非常快速地运行. Microbenchmark当然表明Rcpp减少了计算时间.

我从来没有使用过C++,但我知道当我编译C代码时,我会得到一个*.exe文件.我从一个名为logabs2.exe但找不到的文件中搜索了我的硬盘.我想知道如果logabs2.exe创建文件,上述C++代码是否可能运行得更快.是否可以创建一个logabs2.exe文件并将其存储在某个文件夹中,然后每当我想使用它时让Rcpp调用该文件?我不知道这是否合理.如果我可以在*.exe文件中存储C++函数,那么每次我想要将它与Rcpp一起使用时我可能不需要编译该函数,那么Rcpp代码可能会更快.

对不起,如果这个问题没有意义或是重复的话.如果可以将C++函数存储为*.exe文件,我希望有人会告诉我如何修改上面的R代码来运行它.感谢您对此的任何帮助,或直接告诉我为什么我的建议不可行或不推荐.

我期待看到德克的新书.

Mar*_*ler 6

感谢user1981275,Dirk Eddelbuettel和Romain Francois的回复.下面是我编译C++文件并创建*.dll的方法,然后调用并使用里面的*.dll文件R.

步骤1.我创建了一个名为'c:\ users\mmiller21\myrpackages'的新文件夹,并将文件'logabs2.cpp'粘贴到该新文件夹中.文件'logabs2.cpp'是按照原始帖子中的描述创建的.

步骤2.在新文件夹中,我R使用R我编写的名为"new package creation.r" 的文件创建了一个名为"logabs2" 的新包.'new package creation.r'的内容是:

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

library(Rcpp)

Rcpp.package.skeleton("logabs2", example_code = FALSE, cpp_files = c("logabs2.cpp"))
Run Code Online (Sandbox Code Playgroud)

Rcpp.package.skeleton在Hadley Wickham的一个网站上找到了上述语法:https: //github.com/hadley/devtools/wiki/Rcpp

步骤3.我在DOS命令窗口RR使用以下行安装了新包"logabs2" :

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
Run Code Online (Sandbox Code Playgroud)

哪里:

rcmd.exe文件的位置是:

C:\Program Files\R\R-3.0.1\bin\x64>
Run Code Online (Sandbox Code Playgroud)

R我的计算机上安装的软件包的位置是:

c:\users\mmiller21\documents\r\win-library\3.0\
Run Code Online (Sandbox Code Playgroud)

并且在R安装之前我的新包的位置是:

c:\users\mmiller21\myrpackages\
Run Code Online (Sandbox Code Playgroud)

DOS命令窗口中使用的语法是通过反复试验找到的,可能并不理想.在某些时候,我在'C:\ Program Files\R\R-3.0.1\bin\x64>中粘贴了'logabs2.cpp'的副本,但我认为这不重要.

步骤4.安装新R软件包后,我使用R'c:/ users/mmiller21/myrpackages /'文件夹中名为'new package usage.r' 的文件运行它(虽然我不认为该文件夹很重要).'new package usage.r'的内容是:

library(logabs2)
logabs2(seq(-5, 5, by=2))
Run Code Online (Sandbox Code Playgroud)

输出是:

# [1] 1.609438 1.098612 0.000000 0.000000 1.098612 1.609438
Run Code Online (Sandbox Code Playgroud)

这个文件加载包Rcpp没有我问.

在这种情况下R,假设我做得正确,基数更快.

#> 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
Run Code Online (Sandbox Code Playgroud)

但是,使用dll文件比调用外部cpp文件更快:

system.time(

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

)

#   user  system elapsed 
#   0.06    0.08    5.85 
Run Code Online (Sandbox Code Playgroud)

虽然在这种情况下基数R看起来比*.dll文件更快或更快,但我毫不怀疑在大多数情况下使用*.dll文件Rcpp会比基数快R.

这是我第一次尝试创建R包或使用Rcpp,毫无疑问我没有使用最有效的方法.另外,我为这篇文章中的任何印刷错误道歉.

编辑

在下面的评论中,我认为Romain Francois建议我将*.cpp文件修改为以下内容:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]

NumericVector logabs(NumericVector x) {
return log(abs(x));
}
Run Code Online (Sandbox Code Playgroud)

并重新创建我的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)
Run Code Online (Sandbox Code Playgroud)

基数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
Run Code Online (Sandbox Code Playgroud)

也许这是因为base R已经被矢量化了.我怀疑更复杂的功能基础R会慢得多.或许我仍然没有使用最有效的方法,或者我只是在某个地方犯了错误.


Dir*_*tel 5

你说

直到现在我从未使用过 C++,但我知道当我编译 C 代码时,我会得到一个 *.exe 文件

当且仅当您构建一个可执行文件时,这是正确的。在这里,我们构建了可动态加载的库,然后这些库会根据操作系统具有不同的扩展名:Windoze 为 .dll,Linux 为 .so,OS X 为 .dynlib。

所以这里没有错,你只是有一个错误的假设。