运行编译的c++代码与Rcpp
r - Running compiled C++ code with Rcpp
我一直在学习Dirk Eddelbuettel的Rcpp
教程:
我已经学会了如何在目录中保存一个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;
}
我用下面的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
我在Windows 7机器上从R GUI内运行代码,似乎默认安装。我还安装了最新版本的Rtools
。上面的R代码似乎需要相当长的时间来运行。我怀疑大部分时间都花在编译c++代码上,而一旦编译完c++代码,它就会运行得非常快。Microbenchmark
确实表明Rcpp
减少了计算时间。
我从来没有使用过c++直到现在,但我知道,当我编译C代码我得到一个*.exe文件。我从一个名为logabs2.exe
的文件中搜索了我的硬盘,但找不到一个。我想知道如果创建了logabs2.exe
文件,上述c++代码是否可以运行得更快。是否有可能创建一个logabs2.exe
文件并将其存储在某个文件夹中,然后在我想使用它时让Rcpp调用该文件?我不知道这是否有意义。如果我可以将c++函数存储在*.exe文件中,那么也许我就不必每次在Rcpp中使用它时都编译该函数,那么Rcpp代码可能会更快。
对不起,如果这个问题没有意义或重复。如果有可能将c++函数存储为*.exe文件,我希望有人会告诉我如何修改上面的R代码来运行它。谢谢你在这方面的任何帮助,或者让我明白为什么我的建议是不可能的或不推荐的。
我很期待看到德克的新书。感谢user1981275、Dirk Eddelbuettel和Romain Francois的回复。下面是我如何编译一个c++文件并创建一个*.dll,然后在R
中调用和使用该*.dll文件。
步骤1。我创建了一个名为"c:usersmmiller21myrpackages"的新文件夹,并将文件"logabs2.cpp"粘贴到该新文件夹中。文件'logabs2.cpp'是按照我的原始帖子中的描述创建的。
步骤2。在新文件夹中,我使用我编写的名为"new package creation.r"的R
文件创建了一个名为"logabs2"的新R
包。创建新包的内容。r":
setwd('c:/users/mmiller21/myrpackages/')
library(Rcpp)
Rcpp.package.skeleton("logabs2", example_code = FALSE, cpp_files = c("logabs2.cpp"))
我在Hadley Wickham的一个网站上找到了上面的Rcpp.package.skeleton
语法:https://github.com/hadley/devtools/wiki/Rcpp
步骤3。我在R
中安装了新的R
包"logabs2",在DOS命令窗口中使用以下行:
C:Program FilesRR-3.0.1binx64>R CMD INSTALL -l c:usersmmiller21documentsrwin-library3.0 c:usersmmiller21myrpackageslogabs2
地点:
rcmd.exe文件的位置为:
C:Program FilesRR-3.0.1binx64>
我的计算机上安装的R
包的位置是:
c:usersmmiller21documentsrwin-library3.0
和我的新R
包在安装之前的位置是:
c:usersmmiller21myrpackages
DOS命令窗口中使用的语法是通过反复试验发现的,可能不理想。在某个时候,我在"C:Program FilesRR-3.0.1binx64>"中粘贴了一个"logabs2.cpp"的副本,但我认为这无关紧要。
步骤4。在安装了新的R
包之后,我使用一个名为"新包使用"的R
文件来运行它。r'在'c:/users/mmiller21/myrpackages/'文件夹(虽然我不认为这个文件夹很重要)。"新包用法"的内容。r":
library(logabs2)
logabs2(seq(-5, 5, by=2))
输出为:
# [1] 1.609438 1.098612 0.000000 0.000000 1.098612 1.609438
这个文件没有经过我的请求就加载了Rcpp
包。
在本例中,假设我正确操作,base 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
但是,使用dll文件比调用外部cpp文件要快:
system.time(
cppFunction("
NumericVector logabs(NumericVector x) {
return log(abs(x));
}
")
)
# user system elapsed
# 0.06 0.08 5.85
虽然在这种情况下,基础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));
}
并重新创建我的R
包,我现在已经完成了。然后,使用以下代码将基本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
仍然快一点,或者没有什么不同:
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
这可能是因为基数R
已经矢量化了。我怀疑更复杂的函数基础R
将慢得多。或者我仍然没有使用最有效的方法,或者我只是在某个地方犯了一个错误。
你说
我从来没有使用过c++直到现在,但我知道当我编译C代码我得到一个*.exe文件
,当且仅当您构建可执行时,这是正确的。这里,我们构建可动态加载的库,这些库根据操作系统的不同有不同的扩展名:windows的。dll, Linux的。so, OS x的。dynlib。
所以这里没有错,你只是假设错了。
如果你想要得到一些你可以保留的实体,你正在寻找的是一个R
包。网上有很多资源可以学习如何制作它们(例如Hadley的幻灯片)。
我们有Rcpp.package.skeleton
你可能会发现有用的。
因此,该函数在安装包时编译一次,然后您只需使用它。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么我的 Rcpp 代码比 glmnet 慢得多?
- R-使用RCPP时如何并行C 代码
- 为什么我的RCPP代码给出意外的所有整数值输出
- 如何在代码中使用 Rcpp::Blocks IDE
- Rcpp:从全局环境调用一个R函数,并在C++代码中使用它
- R -RCPP-如何在C 代码中使用分布功能
- 将 Rcpp 与 C 代码链接,以实现自适应城域拒绝采样
- 优化 RCPP 代码
- RCPP代码崩溃
- RCpp:如何在不重新启动R的情况下重新加载重新编译的C++代码
- r语言 - 在 Windows 上使用 Rcpp 创建.dll文件并编译C++代码
- Rcpp:将数据帧与 Rcpp(内联)一起使用时推荐的代码结构
- OpenMP 在 SEIR 模型的 Rcpp 代码中生成段错误
- 我可以像 Rcpp 在 Julia 中的 stop() 一样在 c 代码中抛出错误吗
- 使用Rcpp使用最新的QuantLib代码
- 加载Rcpp并运行示例代码
- 运行编译的c++代码与Rcpp
- 元素矩阵乘法:R与Rcpp(如何加速这段代码?)
- 使用RStudio在R包中编译Rcpp代码时出错