[Rcpp-devel] arma::mat and Rcpp::NumericMatrix

Jeffrey Pollock jeffpollock9 at gmail.com
Fri Sep 16 15:48:03 CEST 2011


Hello all,

I've recently started looking into the speed gains from using Rcpp and have
began looking into the arma library too. Ive written a small loop to fill in
a matrix and done so using the arma::mat class and the Rcpp::NumericMatrix
class. In this case, the Rcpp::NumericMatrix class was slightly faster. Is
this usually the case, or have I written quite inefficient code in some
parts? It's my understanding that the advantage of the arma::mat is that is
has more methods associated with it, is this correct?

I've also added an R function to do this and as per usual, the speed gain of
simply using Rcpp is incredible!

Any input massively appreciated

Jeff

library(RcppArmadillo)
library(inline)
library(rbenchmark)

# start with R function....

fillMiddleTheta <- function(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem) {
    alphaCounter <- alphaCounterStart
    for (i in (thetaStartIndex + 1L):(thetaEndIndex - 1L)) {
        addition <- exp(alphas[alphaCounter] + alphas[alphaCounter + 1L] *
timerem)
        thetaMatrix[ , i] <- thetaMatrix[ , i - 1L] + addition
        alphaCounter <- alphaCounter + 2L
    }
    return(thetaMatrix)
}

# cpp function....

src <- '
        Rcpp::NumericMatrix thetaMatrix(sthetaMatrix);

        Rcpp::NumericVector alphas(salphas);
        Rcpp::NumericVector timerem(stimerem);

        int thetaStartIndex = as<int>(sthetaStartIndex);
        int thetaEndIndex = as<int>(sthetaEndIndex);
        int alphaCounterStart = as<int>(salphaCounterStart);

        int alphaCounter = alphaCounterStart;

        for (int i = thetaStartIndex + 1; i <= thetaEndIndex - 1; i++) {

        thetaMatrix(_, i - 1) = thetaMatrix(_, i - 2) +
exp(alphas(alphaCounter - 1) + alphas(alphaCounter) * timerem);
        alphaCounter = alphaCounter + 2;

        }

        return wrap(thetaMatrix);
        '

cppFillMiddleTheta <- cxxfunction(signature(sthetaMatrix = "Matrix",
sthetaStartIndex = "integer",
                sthetaEndIndex = "integer", salphas = "numericVector",
salphaCounterStart = "integer", stimerem = "numericVector"),
        src, "Rcpp")

# cpp function with armadillo....

armaSrc <- '
        arma::mat thetaMatrix = Rcpp::as<arma::mat>(sthetaMatrix);

        arma::colvec alphas = Rcpp::as<arma::colvec>(salphas);
        arma::colvec timerem = Rcpp::as<arma::colvec>(stimerem);

        int thetaStartIndex = as<int>(sthetaStartIndex);
        int thetaEndIndex = as<int>(sthetaEndIndex);
        int alphaCounterStart = as<int>(salphaCounterStart);

        int alphaCounter = alphaCounterStart;

        for (int i = thetaStartIndex + 1; i <= thetaEndIndex - 1; i++) {

        thetaMatrix.col(i - 1) = thetaMatrix.col(i - 2) +
exp(alphas(alphaCounter - 1) + alphas(alphaCounter) * timerem);
        alphaCounter = alphaCounter + 2;

        }

        return wrap(thetaMatrix);
        '

cppArmaFillMiddleTheta <- cxxfunction(signature(sthetaMatrix = "Matrix",
sthetaStartIndex = "integer",
                sthetaEndIndex = "integer", salphas = "numericVector",
salphaCounterStart = "integer", stimerem = "numericVector"),
        armaSrc, "RcppArmadillo")

# test
n <- 1e6

thetaMatrix <- matrix(0, ncol = 10, nrow = 10)
thetaMatrix[, 1L] <- 1
thetaMatrix[, 10L] <- 100
thetaStartIndex <- 1L
thetaEndIndex <- 10L
alphas <- seq(0, 0.06, length = 16)
alphaCounterStart <- 1L
timerem <- rnorm(10, mean = 40, sd = 2)

r <- fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex, alphas,
alphaCounterStart, timerem)
cpp <- cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem)
cppArma <- cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex,
thetaEndIndex, alphas, alphaCounterStart, timerem)
all.equal(r, cpp, cppArma)

benchmark(fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
        cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
        cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),

        columns = c("test", "replications", "elapsed", "relative",
"user.self", "sys.self"),
        order = "relative",
        replications = n)

Here is some of my output;

> n <- 1e6
> r <- fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex, alphas,
alphaCounterStart, timerem)
> cpp <- cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem)
> cppArma <- cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex,
thetaEndIndex, alphas, alphaCounterStart, timerem)
> all.equal(r, cpp, cppArma)
[1] TRUE

> benchmark(fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
+         cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
+         cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex,
thetaEndIndex, alphas, alphaCounterStart, timerem),
+
+         columns = c("test", "replications", "elapsed", "relative",
"user.self", "sys.self"),
+         order = "relative",
+         replications = n)
> benchmark(fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
+         cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem),
+         cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex,
thetaEndIndex, alphas, alphaCounterStart, timerem),
+
+         columns = c("test", "replications", "elapsed", "relative",
"user.self", "sys.self"),
+         order = "relative",
+         replications = n)


test replications elapsed relative user.self sys.self
2     cppFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem)      1000000   12.22 1.000000
12.17     0.01
3 cppArmaFillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem)      1000000   15.07 1.233224
15.01     0.02
1        fillMiddleTheta(thetaMatrix, thetaStartIndex, thetaEndIndex,
alphas, alphaCounterStart, timerem)      1000000   86.62 7.088380
86.02     0.10
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110916/7afc0696/attachment.html>


More information about the Rcpp-devel mailing list