我第一次尝试了Rcpp功能inline,它解决了我的速度问题(感谢Dirk!):
R:将负值替换为零
初始版本看起来像这样:
library(inline)
cpp_if_src <- '
Rcpp::NumericVector xa(a);
int n_xa = xa.size();
for(int i=0; i < n_xa; i++) {
if(xa[i]<0) xa[i] = 0;
}
return xa;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
Run Code Online (Sandbox Code Playgroud)
但是当被调用时cpp_if(p),它会p用输出覆盖,这不是预期的.所以我认为它是通过引用传递的.
所以我用以下版本修复它:
library(inline)
cpp_if_src <- '
Rcpp::NumericVector xa(a);
int n_xa = xa.size();
Rcpp::NumericVector xr(a);
for(int i=0; i < n_xa; i++) {
if(xr[i]<0) xr[i] = 0;
}
return xr;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
Run Code Online (Sandbox Code Playgroud)
这似乎有效.但是现在,当我将其重新加载到R中时,原始版本不再覆盖其输入(即,相同的确切代码现在不会覆盖其输入):
> cpp_if_src <- '
+ Rcpp::NumericVector …Run Code Online (Sandbox Code Playgroud) 是否有任何理由为什么我应该更喜欢Rcpp::NumericVector过std::vector<double>?
例如,下面的两个功能
// [[Rcpp::export]]
Rcpp::NumericVector foo(const Rcpp::NumericVector& x) {
Rcpp::NumericVector tmp(x.length());
for (int i = 0; i < x.length(); i++)
tmp[i] = x[i] + 1.0;
return tmp;
}
// [[Rcpp::export]]
std::vector<double> bar(const std::vector<double>& x) {
std::vector<double> tmp(x.size());
for (int i = 0; i < x.size(); i++)
tmp[i] = x[i] + 1.0;
return tmp;
}
Run Code Online (Sandbox Code Playgroud)
在考虑其工作和基准性能时是等效的.我知道Rcpp提供了糖和矢量化操作,但是如果只是将R的向量作为输入并将向量作为输出返回,那么我使用哪一个会有什么区别吗?std::vector<double>在与R交互时可以使用导致任何可能的问题吗?
这个问题关系到这个和这个。此处的区别在于,我没有传递Rcpp类型(例如NumericVector或)NumericMatrix,而是传递arma::sp_mat。
有什么方法可以将A传递sp_mat给C ++,修改其值,并使更改显示在R中的原始对象中吗?
可以使用来完成NumericMatrix,例如:
cppFunction("void frob(NumericMatrix& x)
{
for(NumericMatrix::iterator it = x.begin(); it != x.end(); ++it)
{
if(*it != 0) *it = *it + 5;
}
}")
M <- Matrix(0, 5, 1, sparse=TRUE)
M[1] <- 1.2345
m <- as.matrix(M)
frob(m)
m
#[,1]
#[1,] 6.2345
#[2,] 0.0000
#[3,] 0.0000
#[4,] 0.0000
#[5,] 0.0000
Run Code Online (Sandbox Code Playgroud)
相同的技术适用于arma::mat密集矩阵。但是对于稀疏矩阵,它不起作用:
cppFunction("void frob2(arma::sp_mat& x)
{
for(arma::sp_mat::iterator it = x.begin(); it != x.end(); …Run Code Online (Sandbox Code Playgroud)