在R中,矩阵乘法非常优化,即实际上只是对BLAS/LAPACK的调用.但是,我很惊讶这个非常天真的C++代码用于矩阵向量乘法似乎可靠地快了30%.
library(Rcpp)
# Simple C++ code for matrix multiplication
mm_code =
"NumericVector my_mm(NumericMatrix m, NumericVector v){
int nRow = m.rows();
int nCol = m.cols();
NumericVector ans(nRow);
double v_j;
for(int j = 0; j < nCol; j++){
v_j = v[j];
for(int i = 0; i < nRow; i++){
ans[i] += m(i,j) * v_j;
}
}
return(ans);
}
"
# Compiling
my_mm = cppFunction(code = mm_code)
# Simulating data to use
nRow = 10^4
nCol = 10^4
m = matrix(rnorm(nRow * nCol), …Run Code Online (Sandbox Code Playgroud) 我想研究一下rcpp,以提高我的一些R代码的速度,而不必诉诸凌乱的C++代码(我已经取得了一些成功,但它看起来像是来自地狱的代码).
因此,我检查了Rcpp提供的文档,以及Dirk Eddelbuettel网站上提供的文档包.我安装并查看了RcppExamples,但是(至少从它的文档中)大多数都引用了RcppClassic?.除此之外,我做了一些谷歌搜索,但这并没有导致看起来像基本问题的答案.
operator()和
operator[],但显然不是
operator[[]].目前尚不清楚哪些[]与[[]]R 相似.注意:事实上我从Rcpp-introduction.pdf的第一个例子中找到了一些答案,但这感觉就像运气.
此外,我stl非常生疏,所以如果有人能给我一个简单的例子,其中List的每个元素都是(例如)print-ed与stl风格的循环,那将是整洁的.
如果有人想因为没有找到这些信息而称我为白痴:继续前进,让你的一天.然后制作我的并指向我需要的文档:-)
作为对Eddelbuettel先生和其他Rcpp作者的建议(我希望他们中的一些人能够读到这一点):doxygen提供的类层次结构等,当你已经深入Rcpp时,它真的很整洁,但对于初学者来说(在Rcpp),我更感兴趣的是这个类中的这个方法的列表就像R中的那个函数一样,而不是'你可以在这个头文件中找到这个运算符的声明'.毕竟,我理解Rcpp的目标之一是降低在R中使用C++的门槛?注意:从我所看到和理解的内容来看,我非常重视Rcpp的实际代码,并对其创建者表示最高的敬意.如果缺乏基本文档仅仅是"缺乏资源"的结果,我愿意成为一种资源(例如:一旦我自己完成了"基本"文档的工作).
我有兴趣在OS X(Mountain Lion 10.8.2)下分析一些Rcpp代码,但是分析器在运行时崩溃了.
玩具示例,使用inline,只是为了让探查器注意到足够的时间.
library(Rcpp)
library(inline)
src.cpp <- "
RNGScope scope;
int n = as<int>(n_);
double x = 0.0;
for ( int i = 0; i < n; i++ )
x += (unif_rand()-.5);
return wrap(x);"
src.c <- "
int i, n = INTEGER(n_)[0];
double x = 0.0;
GetRNGstate();
for ( i = 0; i < n; i++ )
x += (unif_rand()-.5);
PutRNGstate();
return ScalarReal(x);"
f.cpp <- cxxfunction(signature(n_="integer"), src.cpp, plugin="Rcpp")
f.c <- cfunction(signature(n_="integer"), src.c)
Run Code Online (Sandbox Code Playgroud)
如果我使用GUI Instruments(在Xcode,版本4.5(4523)中)或命令行sample,两者都崩溃:仪器立即崩溃,而样本在崩溃前完成处理样本: …
首先我要说的是我读过写R扩展,Rcpp包的插图,以及我已经构建了一个包Rcpp.package.skeleton().
自从构建我的包之后,我添加了一个函数,multiGenerateCSVrow()然后compileAttributes()在R CMD build/R CMD安装之前在包目录上运行.之后予加载我包,我可以直接地或通过运行我功能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"
Run Code Online (Sandbox Code Playgroud)
这是NAMESPACE包:
# Generated by roxygen2 (4.0.1): do not edit by hand
useDynLib(myPackage)
exportPattern("^[[:alpha:]]+")
importFrom(Rcpp, evalCpp)
Run Code Online (Sandbox Code Playgroud)
这是RcppExports.cpp的相关块:
// multiGenerateCSVrow
SEXP …Run Code Online (Sandbox Code Playgroud) 我正在尝试让内联包在我的macbook上运行.以下代码块(来自cxxfunction示例)失败:
library(inline)
fx <- cxxfunction( signature(x = "integer", y = "numeric" ) , '
return ScalarReal( INTEGER(x)[0] * REAL(y)[0] ) ;
' )
fx( 2L, 5 )
Run Code Online (Sandbox Code Playgroud)
出现此错误:
Error in compileCode(f, code, language = language, verbose = verbose) :
Compilation ERROR, function(s)/method(s) not created! make: g++-4.2: No such file or directory
make: *** [file141b5882.o] Error 1
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为g ++可用:
g++ -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.1~22/src/configure --disable-checking --enable-werror --prefix=/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.1~22/dst-llvmCore/Developer/usr/local …Run Code Online (Sandbox Code Playgroud) 我试图在Rcpp函数中打开一个文件,所以我需要文件名作为char*或std :: string.
到目前为止,我尝试过以下方法:
#include <Rcpp.h>
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <string>
RcppExport SEXP readData(SEXP f1) {
Rcpp::CharacterVector ff(f1);
std::string fname = Rcpp::as(ff);
std::ifstream fi;
fi.open(fname.c_str(),std::ios::in);
std::string line;
fi >> line;
Rcpp::CharacterVector rline = Rcpp::wrap(line);
return rline;
}
Run Code Online (Sandbox Code Playgroud)
但显然,因为我得到编译时错误as不起作用Rcpp::CharacterVector.
foo.cpp: In function 'SEXPREC* readData(SEXPREC*)':
foo.cpp:8: error: no matching function for call to 'as(Rcpp::CharacterVector&)'
make: *** [foo.o] Error 1
Run Code Online (Sandbox Code Playgroud)
有没有一种简单的方法从参数中获取字符串或以某种方式从Rcpp函数参数中打开文件?
这是我第一次尝试Rcpp,这个非常简单的问题给了我麻烦.我想使用嵌套for循环来操作矩阵的各个值,一次一列.我瞄准的脚本看起来像这样:
src <- '
Rcpp::NumericMatrix Am(A);
int nrows = Am.nrow();
int ncolumns = Am.ncol();
for (int i = 0; i < ncolumns; i++){
for (int j = 1; j < nrows; j++){
Am[j,i] = Am[j,i] + Am[j-1,i];
}
}
return Am;
'
fun <- cxxfunction(signature(A = "numeric"), body = src, plugin="Rcpp")
fun(matrix(1,4,4))
Run Code Online (Sandbox Code Playgroud)
期望的输出是这样的:
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
[4,] 4 4 4 4
Run Code Online (Sandbox Code Playgroud)
问题显然在这一行,我不知道如何引用矩阵的各个元素.
Am[j,i] = …Run Code Online (Sandbox Code Playgroud) 最近我一直在尝试使用Rcpp(内联)来生成DLL,这些DLL在提供的R输入上执行各种任务.在给定一组特定的R输入的情况下,我希望能够逐行调试这些DLL中的代码.(我在Windows下工作.)
为了说明,让我们考虑一个任何人都应该能够运行的具体例子......
下面的代码是一个非常简单的cxx函数,它只是输入向量的两倍.但请注意,有一个额外的变量myvar可以更改值几次,但不会影响输出 - 这已添加,以便我们能够看到调试过程何时正确运行.
library(inline)
library(Rcpp)
f0 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int myvar = 19;
int na = xa.size();
myvar = 27;
Rcpp::NumericVector out1(na);
for(int i=0; i < na; i++) {
out1[i] = 2*xa[i];
myvar++;
}
myvar = 101;
return(Rcpp::List::create( _["out1"] = out1));
')
Run Code Online (Sandbox Code Playgroud)
运行上面的命令之后,输入命令
getLoadedDLLs()
Run Code Online (Sandbox Code Playgroud)
在R会话中显示DLL列表.列出的最后一个应该是由上面的过程创建的DLL - 它有一个随机的临时名称,在我的情况下是
file7e61645c
Run Code Online (Sandbox Code Playgroud)
"Filename"列显示cxxfunction已将此DLL放在该位置tempdir(),这对我来说是当前的位置
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
Run Code Online (Sandbox Code Playgroud)
现在,调用DLL的明显方法是via f0,如下所示
> f0(c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
Run Code Online (Sandbox Code Playgroud)
但我们当然也可以使用以下.Call命令直接通过名称调用DLL :
> .Call("file7e61645c",c(-7,0.7,77))
$out1
[1] -14.0 …Run Code Online (Sandbox Code Playgroud) 我目前正在研究一种贝叶斯方法,该方法需要在每次迭代中对多项式 logit 模型进行多个优化步骤。我正在使用 optim() 来执行这些优化,并使用 R 编写的目标函数。分析显示 optim() 是主要瓶颈。
在挖掘之后,我发现了这个问题,他们建议重新编码目标函数Rcpp可以加快进程。我遵循了建议并用 重新编码了我的目标函数Rcpp,但它最终变慢了(大约慢了两倍!)。
这是我第一次使用Rcpp(或任何与 C++ 相关的东西),我无法找到一种对代码进行矢量化的方法。知道如何使它更快吗?
Tl; dr:当前 Rcpp 中函数的实现不如矢量化 R 快;如何让它更快?
一个可重现的例子:
Rand 中定义目标函数Rcpp:仅截取多项式模型的对数似然library(Rcpp)
library(microbenchmark)
llmnl_int <- function(beta, Obs, n_cat) {
n_Obs <- length(Obs)
Xint <- matrix(c(0, beta), byrow = T, ncol = n_cat, nrow = n_Obs)
ind <- cbind(c(1:n_Obs), Obs)
Xby <- Xint[ind]
Xint <- exp(Xint)
iota <- c(rep(1, (n_cat)))
denom <- log(Xint %*% iota)
return(sum(Xby …Run Code Online (Sandbox Code Playgroud) 我们希望将数组中的所有值设置为负值.我尝试了很多东西,但还没有找到一个有效的解决方案.我想到了一个带有条件的for循环,但这似乎不起作用.
#pred_precipitation is our array
pred_precipitation <-rnorm(25,2,4)
for (i in nrow(pred_precipitation))
{
if (pred_precipitation[i]<0) {pred_precipitation[i] = 0}
else{pred_precipitation[i] = pred_precipitation[i]}
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的提示!
r ×10
rcpp ×10
c++ ×1
debugging ×1
dll ×1
for-loop ×1
gdb ×1
if-statement ×1
inline ×1
optimization ×1
osx-lion ×1
performance ×1
profiling ×1
xcode ×1