2

I want to use arma::mat for my list of matrices.

Converting R matrix to arma::mat is working well with const.

But when i use List with matrices as an arguments, It takes very long time.

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
int check1(List X)
{
   int i;
   for (i = 0; i < 10; i ++)
      arma::mat y = as<arma::mat>(X[i]);
   return 0;
}
// [[Rcpp::export]]
int check2(const List& X)
{
   int i;
   for (i = 0; i < 10; i ++)
      arma::mat y = as<arma::mat>(X[i]);
   return 0;
}
// [[Rcpp::export]]
int check3(List X)
{
   int i;
   for (i = 0; i < 10; i ++)
      NumericMatrix y = X[i];
   return 0;
}
matlist = lapply(1:10, function(x) matrix(rnorm(10000), 2000, 50))
microbenchmark::microbenchmark(
   arma = check1(matlist),
   carma = check2(matlist),
   nm = check3(matlist)
)
Unit: microseconds
  expr     min       lq      mean  median      uq      max neval
  arma 558.081 597.6485 622.13757 614.702 625.928 1303.494   100
 carma 551.950 600.4425 658.33583 612.761 626.683 1749.153   100
    nm   2.288   4.3590   5.57801   5.123   5.901   39.743   100

1 Answers1

4

It seems that there are some copies happening, which slows down your code.

To prevent copies when creating Armadillo matrices, one solution is:

// [[Rcpp::export]]
int check4(List X)
{
  int i;
  for (i = 0; i < 10; i ++) {
    NumericMatrix x = X[i];
    arma::mat y = arma::mat(x.begin(), x.nrow(), x.ncol(), false);
  }
  return 0;
}

Benchmark:

Unit: microseconds
    expr     min       lq      mean   median       uq      max neval
    arma 599.669 606.5465 634.41683 610.4185 632.4370 1519.262   100
   carma 600.506 606.0975 624.18013 609.8885 629.5135 1327.891   100
      nm   2.100   2.5030  10.88695   3.5180   4.2670  743.220   100
 nm_arma   2.949   3.3160  11.48330   4.7625   5.3195  685.302   100

PS: const and & won't change anything to your Rcpp code. See section 5.1 of https://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-FAQ.pdf.

F. Privé
  • 11,423
  • 2
  • 27
  • 78
  • 1
    Using the [advanced constructors](http://arma.sourceforge.net/docs.html#adv_constructors_mat) is the way to go. This happens automatically for `const arma::mat&` arguments! – Ralf Stubner Aug 16 '19 at 07:59
  • Your reading of Section 5.1 of the Rcpp FAQ is not quite right. The `&` is superfluous due to the proxy model, and `const` can be gotten around by creating a new `SEXP` from the supposedly `const` one, but `const` will prevent you from modifying the original `SEXP`. Try the following function: `void const_mod(const Rcpp::IntegerVector& x) { x = x + 1; }` on data such as `x <- 1:5` (note you will have to compile with `-fpermissive`). You'll see `x` is not modified. – duckmayr Aug 16 '19 at 16:37