简体   繁体   English

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

[英]Running compiled C++ code with Rcpp

I have been working my way through Dirk Eddelbuettel's Rcpp tutorial here: 我一直在努力通过Dirk Eddelbuettel的Rcpp教程:

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

I have learned how to save a C++ file in a directory and call it and run it from within R. The C++ file I am running is called 'logabs2.ccp' and its contents are directly from one of Dirk's slides: 我已经学会了如何在目录中保存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;
}

I run it with this R code: 我用这个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

I am running the code on a Windows 7 machine from within the R GUI that seems to install by default. 我在R GUI中运行Windows 7计算机上的代码,默认情况下似乎安装。 I also installed the most recent version of Rtools . 我还安装了最新版本的Rtools The above R code seems to take a relatively long time to run. 上面的R代码似乎需要相对较长的时间才能运行。 I suspect most of that time is devoted to compiling the C++ code and that once the C++ code is compiled it runs very quickly. 我怀疑大部分时间都用于编译C ++代码,而且一旦编译C ++代码,它就会非常快速地运行。 Microbenchmark certainly suggests that Rcpp reduces computation time. Microbenchmark肯定表明Rcpp减少了计算时间。

I have never used C++ until now, but I know that when I compile C code I get an *.exe file. 我从来没有使用过C ++,但我知道当我编译C代码时,我会得到一个* .exe文件。 I have searched my hard-drive from a file called logabs2.exe but cannot find one. 我从一个名为logabs2.exe的文件中搜索了我的硬盘驱动器,但找不到一个。 I am wondering whether the above C++ code might run even faster if a logabs2.exe file was created. 我想知道如果创建logabs2.exe文件,上述C ++代码是否可能运行得更快。 Is it possible to create a logabs2.exe file and store it in a folder somewhere and then have Rcpp call that file whenever I wanted to use it? 是否可以创建一个logabs2.exe文件并将其存储在某个文件夹中,然后每当我想使用它时让Rcpp调用该文件? I do not know whether that makes sense. 我不知道这是否合理。 If I could store a C++ function in an *.exe file then perhaps I would not have to compile the function every time I wanted to use it with Rcpp and then perhaps the Rcpp code would be even faster. 如果我可以在* .exe文件中存储C ++函数,那么每次我想要将它与Rcpp一起使用时我可能不需要编译该函数,那么Rcpp代码可能会更快。

Sorry if this question does not make sense or is a duplicate. 对不起,如果这个问题没有意义或是重复的话。 If it is possible to store the C++ function as an *.exe file I am hoping someone will show me how to modify my R code above to run it. 如果可以将C ++函数存储为* .exe文件,我希望有人会告诉我如何修改上面的R代码来运行它。 Thank you for any help with this or for setting me straight on why what I suggest is not possible or recommended. 感谢您对此提供任何帮助,或直接告诉我为什么我的建议不可行或不推荐。

I look forward to seeing Dirk's new book. 我期待看到德克的新书。

Thank you to user1981275, Dirk Eddelbuettel and Romain Francois for their responses. 感谢user1981275,Dirk Eddelbuettel和Romain Francois的回复。 Below is how I compiled a C++ file and created a *.dll, then called and used that *.dll file inside R . 下面是我编译C ++文件并创建* .dll的方法,然后调用并使用R中的* .dll文件。

Step 1. I created a new folder called 'c:\\users\\mmiller21\\myrpackages' and pasted the file 'logabs2.cpp' into that new folder. 步骤1.我创建了一个名为'c:\\ users \\ mmiller21 \\ myrpackages'的新文件夹,并将文件'logabs2.cpp'粘贴到该新文件夹中。 The file 'logabs2.cpp' was created as described in my original post. 文件'logabs2.cpp'是按照原始帖子中的描述创建的。

Step 2. Inside the new folder I created a new R package called 'logabs2' using an R file I wrote called 'new package creation.r'. 步骤2.在新文件夹中,我使用我写的名为'new package creation.r'的R文件创建了一个名为'logabs2'的新R包。 The contents of 'new package creation.r' are: 'new package creation.r'的内容是:

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

library(Rcpp)

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

I found the above syntax for Rcpp.package.skeleton on one of Hadley Wickham's websites: https://github.com/hadley/devtools/wiki/Rcpp 我在Hadley Wickham的一个网站上找到了Rcpp.package.skeleton的上述语法: https//github.com/hadley/devtools/wiki/Rcpp

Step 3. I installed the new R package "logabs2" in R using the following line in the DOS command window: 步骤3.我在DOS命令窗口中使用以下行在R安装了新的R包“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

where: 哪里:

the location of the rcmd.exe file is: rcmd.exe文件的位置是:

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

the location of installed R packages on my computer is: 我的计算机上安装的R包的位置是:

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

and the location of my new R package prior to being installed is: 并且在安装之前我的新R包的位置是:

c:\users\mmiller21\myrpackages\

Syntax used in the DOS command window was found by trial and error and may not be ideal. DOS命令窗口中使用的语法是通过反复试验找到的,可能并不理想。 At some point I pasted a copy of 'logabs2.cpp' in 'C:\\Program Files\\R\\R-3.0.1\\bin\\x64>' but I do not think that mattered. 在某些时候,我在'C:\\ Program Files \\ R \\ R-3.0.1 \\ bin \\ x64>中粘贴了'logabs2.cpp'的副本,但我认为这不重要。

Step 4. After installing the new R package I ran it using an R file I named 'new package usage.r' in the 'c:/users/mmiller21/myrpackages/' folder (although I do not think the folder was important). 步骤4.安装新的R包后,我使用R文件运行它,我在'c:/ users / mmiller21 / myrpackages /'文件夹中命名为'new package usage.r'(虽然我不认为该文件夹很重要) 。 The contents of 'new package usage.r' are: 'new package usage.r'的内容是:

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

The output was: 输出是:

# [1] 1.609438 1.098612 0.000000 0.000000 1.098612 1.609438

This file loaded the package Rcpp without me asking. 这个文件在没有我询问的情况下加载了包Rcpp

In this case base R was faster assuming I did this correctly. 在这种情况下,假设我正确地做了这个,基数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

However, using the dll file was faster than calling the external cpp file: 但是,使用dll文件比调用外部cpp文件更快:

system.time(

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

)

#   user  system elapsed 
#   0.06    0.08    5.85 

Although base R seems faster or as fast as the *.dll file in this case, I have no doubt that using the *.dll file with Rcpp will be faster than base R in most cases. 虽然在这种情况下基本R看起来比* .dll文件更快或更快,但我毫不怀疑在大多数情况下使用带有Rcpp的* .dll文件比基本R更快。

This was my first attempt creating an R package or using Rcpp and no doubt I did not use the most efficient methods. 这是我第一次尝试创建R包或使用Rcpp,毫无疑问我没有使用最有效的方法。 Also, I apologize for any typographic errors in this post. 另外,我为这篇文章中的任何印刷错误道歉。

EDIT 编辑

In a comment below I think Romain Francois suggested I modify the *.cpp file to the following: 在下面的评论中,我认为Romain Francois建议我将* .cpp文件修改为以下内容:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]

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

and recreate my R package, which I have now done. 并重新创建我的R包,我现在已经完成了。 I then compared base R against my new package using the following code: 然后我使用以下代码将基本R与我的新包进行比较:

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)

Base R is still a tiny bit faster or no different: Base 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

Perhaps this is because base R is already vectorized. 也许这是因为基础R已经被矢量化了。 I suspect with more complex functions base R will be much slower. 我怀疑更复杂的功能基础R会慢得多。 Or perhaps I am still not using the most efficient approach, or perhaps I simply made an error somewhere. 或许我仍然没有使用最有效的方法,或者我只是在某个地方犯了错误。

You say 你说

I have never used C++ until now, but I know that when I compile C code I get an *.exe file 我从来没有使用过C ++,但我知道当我编译C代码时,我会得到一个* .exe文件

and that is true if and only you build an executable . 只有你构建一个可执行文件才是真的。 Here, we build dynamically loadable libraries and those thend to have different extensionos depending on the operating system: .dll for Windoze, .so for Linux, .dynlib for OS X. 在这里,我们构建动态可加载库以及根据操作系统具有不同扩展名的 :.dll用于Windoze,.so用于Linux,.dynlib用于OS X.

So nothing wrong here, you simply had the wrong assumption. 所以没有错,你只是做了错误的假设。

If you want to get some entity you can keep, what you are looking for is an R package. 如果你想得到一些你可以保留的实体,你要找的是一个R包。 There are many resources online to learn how to make them (eg Hadley's slides ). 网上有很多资源可以学习如何制作它们(例如Hadley的幻灯片 )。

We have Rcpp.package.skeleton you might find useful. 我们有Rcpp.package.skeleton你可能会发现有用。

So, the function is compiled once when the package is installed, and then you just use it. 因此,在安装软件包时,该函数会被编译一次,然后您只需使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM