celestialgod

Rcpp sd test

Jan 17th, 2016
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 4.11 KB | None | 0 0
  1. // based on http://stackoverflow.com/questions/24253228/performance-of-r-statssd-vs-armastddev-vs-rcpp-implementation
  2.  
  3. library(Rcpp)
  4. library(RcppArmadillo)
  5. library(RcppParallel)
  6.  
  7. sourceCpp(code = '
  8. #include <vector>
  9. #include <cmath>
  10. #include <numeric>
  11. // [[Rcpp::plugins(cpp11)]]
  12. //[[Rcpp::depends(RcppArmadillo)]]
  13. #include <RcppArmadillo.h>
  14. // [[Rcpp::depends(RcppParallel)]]
  15. #include <RcppParallel.h>
  16. using namespace Rcpp;
  17.  
  18. struct Sum : public RcppParallel::Worker {
  19.  const RcppParallel::RVector<double> input;
  20.  double value;
  21.  
  22.  Sum(const Rcpp::NumericVector input)
  23.  : input(input), value(0) {}
  24.  Sum(const Sum& sum, RcppParallel::Split)
  25.  : input(sum.input), value(0) {}
  26.  
  27.  void operator()(std::size_t begin, std::size_t end) {
  28.    value += std::accumulate(input.begin() + begin,
  29.                             input.begin() + end,
  30.                             0.0);
  31.  }
  32.  
  33.  void join(const Sum& rhs) {
  34.    value += rhs.value;
  35.  }
  36. };
  37.  
  38.  
  39. struct InnerProduct : public RcppParallel::Worker {
  40.  const RcppParallel::RVector<double> x;
  41.  const RcppParallel::RVector<double> y;
  42.  double mean;
  43.  double product;
  44.  
  45.  InnerProduct(const Rcpp::NumericVector x,
  46.               const Rcpp::NumericVector y,
  47.               const double mean)
  48.  : x(x), y(y), mean(mean), product(0) {}
  49.  
  50.  InnerProduct(const InnerProduct& innerProduct,
  51.               RcppParallel::Split)
  52.  : x(innerProduct.x), y(innerProduct.y),
  53.    mean(innerProduct.mean), product(0) {}
  54.  
  55.  void operator()(std::size_t begin, std::size_t end) {
  56.    product += std::inner_product(x.begin() + begin,
  57.                                  x.begin() + end,
  58.                                  y.begin() + begin,
  59.                                  0.0, std::plus<double>(),
  60.                [&](double lhs, double rhs)->double {
  61.                  return ( (lhs-mean)*(rhs-mean) );
  62.                });
  63.  }
  64.  
  65.  void join(const InnerProduct& rhs) {
  66.    product += rhs.product;
  67.  }
  68. };
  69.  
  70. // [[Rcpp::export]]
  71. double sd_RP(const Rcpp::NumericVector& x_)
  72. {
  73.  int N = x_.size();
  74.  Rcpp::NumericVector y_(x_);
  75.  Sum sum(x_);
  76.  RcppParallel::parallelReduce(0, x_.length(), sum);
  77.  
  78.  double mean = sum.value / N;
  79.  InnerProduct innerProduct(x_, y_, mean);
  80.  RcppParallel::parallelReduce(0, x_.length(), innerProduct);
  81.  
  82.  return std::sqrt( innerProduct.product / (N-1) );
  83. }
  84.  
  85. // [[Rcpp::export]]
  86. double sd_cpp(Rcpp::NumericVector rinVec) {
  87.  std::vector<double> inVec(rinVec.begin(),rinVec.end());
  88.  int n = inVec.size();
  89.  double sum = std::accumulate(inVec.begin(), inVec.end(), 0.0);
  90.  double mean = sum / inVec.size();
  91.  
  92.  for(std::vector<double>::iterator iter = inVec.begin();
  93.      iter != inVec.end();
  94.      ++iter){
  95.    double temp = (*iter - mean)*(*iter - mean);
  96.    *iter = temp;
  97.  }
  98.  
  99.  double sd = std::accumulate(inVec.begin(), inVec.end(), 0.0);
  100.  return std::sqrt( sd / (n-1) );
  101. }
  102.  
  103. //[[Rcpp::export]]
  104. double sd_arma(arma::vec& xin){
  105.  return arma::stddev(xin);
  106. }
  107. //[[Rcpp::export]]
  108. double sd_arma2(arma::vec xin){
  109.  return arma::stddev(xin);
  110. }
  111. //[[Rcpp::export]]
  112. double sd_arma3(NumericVector xin){
  113.  arma::vec x = arma::vec(xin.begin(), xin.size(), false);
  114.  return arma::stddev(x);
  115. }
  116. //[[Rcpp::export]]
  117. double sd_sugar(NumericVector& xin){
  118.  return sd(xin);
  119. }')
  120.  
  121. library(microbenchmark)
  122. set.seed(123)
  123. x <- rnorm(6e6)
  124. microbenchmark(
  125.   sd(x),
  126.   sd_cpp(x),
  127.   sd_arma(x),
  128.   sd_arma2(x),
  129.   sd_arma3(x),
  130.   sd_sugar(x),
  131.   sd_RP(x),
  132.   times=300L,
  133.   control=list(warmup=25))
  134.  
  135. # Unit: milliseconds
  136. #         expr       min        lq      mean   median        uq       max neval
  137. #        sd(x) 22.511043 23.450942 23.765945 23.76388 23.994588 26.869210   300
  138. #    sd_cpp(x) 28.855132 29.302430 29.601853 29.45789 29.753917 31.651868   300
  139. #   sd_arma(x) 22.628647 23.837267 24.102153 24.04160 24.224056 28.056108   300
  140. #  sd_arma2(x) 36.968243 38.796221 39.328432 39.06215 39.688645 42.672182   300
  141. #  sd_arma3(x) 23.078272 23.830440 24.117261 24.03012 24.280841 26.794738   300
  142. #  sd_sugar(x) 14.803495 16.029491 16.218793 16.21459 16.404333 20.748227   300
  143. #     sd_RP(x)  2.164655  2.422824  2.848265  2.83661  3.069336  5.128333   300
Advertisement
Add Comment
Please, Sign In to add comment