C++ 使用RcppArmadillo计算向量的尾和
我写了一个R代码来计算向量的尾和:C++ 使用RcppArmadillo计算向量的尾和,c++,r,rcpp,rcpparmadillo,C++,R,Rcpp,Rcpparmadillo,我写了一个R代码来计算向量的尾和: tailsum <- function(x){ sum(x) + x - cumsum(x) } tailsum x microbenchmark( +尾和(x), +尾水_cpp(x), +泰尔苏姆阿玛(x) + ) 单位:微秒 expr最小lq平均uq最大neval cld 尾款(x)2.0 2.3 2.826 2.5 2.70 14.4 100 a 尾款_cpp(x)1.9 2.1 2.495 2.3 2.60 6.5 100 a tail
tailsum <- function(x){
sum(x) + x - cumsum(x)
}
tailsum x microbenchmark(
+尾和(x),
+尾水_cpp(x),
+泰尔苏姆阿玛(x)
+ )
单位:微秒
expr最小lq平均uq最大neval cld
尾款(x)2.0 2.3 2.826 2.5 2.70 14.4 100 a
尾款_cpp(x)1.9 2.1 2.495 2.3 2.60 6.5 100 a
tailsum_arma(x)2.2.4 3.128 2.6 2.85 30.4 100 a
如何改进用RcppArmadillo编写的代码?(我需要使用RcppArmadillo,因为还有许多其他线性代数操作是使用RcppArmadillo完成的。)有趣的问题,体面的答案。我们可以进一步改进:
- 为了防御性,我建议不要使用
并使用显式引用“只是为了确保”名称空间…
- 不需要包括Rcpp.h,RcppArmadillo.h做了我们所需要的一切(这是一个无操作)
- 你的向量太小了,不重要,我拨到了1e4,1e5,1e6——然后犰狳有时会把R绑在一起,或者“在中间”以微弱优势击败它
- 正如我们所看到的,“基本”R操作是对编译代码的直接和精简调用,因此您不必“击败它们”(除非您使用OpenMP和其他技巧)
- 为什么不将tailsum_cpp和tailsum_self的两个循环合并到一个函数中,以节省调用开销——这是最快的结果
- 尽管如此,我几乎总是选择你的第一种方法,在一行程序中使用犰狳函数
Unit: milliseconds
expr min lq mean median uq max neval cld
r 3.09441 3.58882 7.46590 5.42797 6.79353 181.518 500 b
rcpp 3.57488 4.16185 8.15100 5.83417 7.26449 146.467 500 b
arma 3.09324 3.77172 7.63546 5.50456 8.21274 221.112 500 b
combo 2.72539 2.87299 4.58357 3.16753 4.95350 109.923 500 a
>
代码如下
#包括
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::导出]]
arma::colvec tailsum_arma(const arma::colvec&x){
返回arma::sum(x)+x-arma::cumsum(x);
}
Rcpp::NumericVector累积和自身(常量Rcpp::NumericVector&x){
自动x_len=x.length();
Rcpp::数值向量y(x_len);
y[0]=x[0];
对于(int i=1;i tailsum\r你就不能把它写成一个循环吗?就像你为cumsum做的一样谢谢你!它真的有效!我非常依赖于图书馆的功能,我从来没有想过使用循环来完成这个简单的问题。@ F.PrvIEe感谢你的详细答案和有用的C++技巧,这对我帮助很大。Eddelbuettel@ChenHuang:不客气!请随意选择“向上投票”(点击向上三角形)和/或“接受”(点击勾号,只有你是提问者,请看),以表示答案有帮助/回答你的问题。这就是答案之间的信号和奖励。
> x <- rnorm(1000)
> microbenchmark(
+ tailsum(x),
+ tailsum_cpp(x),
+ tailsum_arma(x)
+ )
Unit: microseconds
expr min lq mean median uq max neval cld
tailsum(x) 2.0 2.3 2.826 2.5 2.70 14.4 100 a
tailsum_cpp(x) 1.9 2.1 2.495 2.3 2.60 6.5 100 a
tailsum_arma(x) 2.2 2.4 3.128 2.6 2.85 30.4 100 a
Unit: milliseconds
expr min lq mean median uq max neval cld
r 3.09441 3.58882 7.46590 5.42797 6.79353 181.518 500 b
rcpp 3.57488 4.16185 8.15100 5.83417 7.26449 146.467 500 b
arma 3.09324 3.77172 7.63546 5.50456 8.21274 221.112 500 b
combo 2.72539 2.87299 4.58357 3.16753 4.95350 109.923 500 a
>
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::colvec tailsum_arma(const arma::colvec &x){
return arma::sum(x) + x - arma::cumsum(x);
}
Rcpp::NumericVector cumsum_self(const Rcpp::NumericVector &x){
auto x_len = x.length();
Rcpp::NumericVector y(x_len);
y[0] = x[0];
for (int i = 1;i < x_len; i++){
y[i] = y[i - 1] + x[i];
}
return y;
}
// [[Rcpp::export]]
Rcpp::NumericVector tailsum_cpp(const Rcpp::NumericVector &x){
//just to compare with tailsum_arma
return sum(x) + x - cumsum_self(x);
}
// [[Rcpp::export]]
Rcpp::NumericVector tailsum_combo(const Rcpp::NumericVector &x){
size_t x_len = x.length();
double x_sum = Rcpp::sum(x);
double csum = 0.0;
Rcpp::NumericVector y(x_len);
for (size_t i = 0; i < x_len; i++) {
csum += x[i];
y[i] = x_sum - csum + x[i];
}
return y;
}
/*** R
# But to my surprise, R code is more efficient than RcppArmadillo code:
tailsum_r <- function(x){
sum(x) + x - cumsum(x)
}
x <- rnorm(1e6)
microbenchmark::microbenchmark(r = tailsum_r(x),
rcpp = tailsum_cpp(x),
arma = tailsum_arma(x),
combo = tailsum_combo(x),
times = 500)
*/