Sum of vector
std::accumulate
#include <Rcpp.h>
// [[Rcpp::export]]
double sumRcpp(const Rcpp::NumericVector& x) {
return std::accumulate(x.begin(), x.end(), 0.0);
}
Loop
#include <Rcpp.h>
// [[Rcpp::export]]
double sumRcpp2(const Rcpp::NumericVector& x) {
std::size_t n = x.size();
double total = 0;
if (n > 0) {
for (std::size_t i = 0, k = n - 1; i < k; ++i, --k)
total += x[i] + x[k];
if (n % 2 == 1)
total += x[n / 2];
}
return total;
}
RcppArmadillo
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
double sumArmadillo(const arma::vec& x) {
return arma::accu(x);
}
RcppEigen
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
typedef Eigen::Map<Eigen::VectorXd> MapNumVec;
// [[Rcpp::export]]
double sumEigen(const MapNumVec& x) {
return x.sum();
}
RcppParalell
// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
#include <Rcpp.h>
using namespace RcppParallel;
struct Sum : Worker {
const RVector<double> input;
double value;
Sum(const Rcpp::NumericVector input) : input(input), value(0) {}
Sum(const Sum& sum, Split) : input(sum.input), value(0) {}
void operator()(std::size_t begin, std::size_t end) {
value += std::accumulate(input.begin() + begin, input.begin() + end, 0.0);
}
void join(const Sum& rhs) {
value += rhs.value;
}
};
// [[Rcpp::export]]
double sumRcppParallel(const Rcpp::NumericVector& x) {
Sum sum(x);
parallelReduce(0, x.size(), sum);
return sum.value;
}
Benchmark function
library(microbenchmark)
library(ggplot2)
theme_set(theme_bw())
bench <- function(..., n = 10e2 * 1:10e2, times = 100) {
exprs <- as.list(match.call(expand.dots = FALSE)$...)
nexprs <- length(exprs)
nout <- nexprs * times
out <- list(n = integer(nout),
expr = factor(integer(nout), levels = as.character(exprs)),
time = numeric(nout))
for (i in seq_along(n)) {
start <- (i - 1) * nexprs + 1
end <- start + nexprs - 1
x <- runif(n[i])
res <- microbenchmark(list = exprs, times = times)
res <- stack(lapply(split(res$time, res$expr), median.default))
out[["n"]][start:end] <- n[i]
out[["expr"]][start:end] <- res$ind
out[["time"]][start:end] <- res$values
}
class(out) <- "data.frame"
attr(out, "row.names") <- .set_row_names(length(out$n))
gp <- ggplot(out, aes(x = n, y = time, linetype = expr, color = expr)) +
geom_smooth(se = FALSE)
print(gp)
invisible(out)
}
Benchmark results
bench(sum(x), sumRcpp(x), sumRcpp2(x),
sumArmadillo(x), sumEigen(x), sumRcppParallel(x))
