[Rcpp-devel] fill a NumericMatrix row by row

Dirk Eddelbuettel edd at debian.org
Wed Mar 27 14:42:56 CET 2013


On 27 March 2013 at 12:06, Michael Love wrote:
| Thanks for the reply and great libraries Conrad and Romain.
| 
| Conrad, my example is a bit too simple maybe, I am really doing:
| 
| for i from 1 to m:
|    do computation
|    store a row of results into a tall m x n matrix
| 
| ...where i am pretty sure that the time required for computation is more than
| storing the results.
| 
| Out of curiosity, I tried to do some profiling for row filling of tall
| Armadillo matrices vs. column filling. Row filling becomes worse when the rows
| are long.  I guess the memory allocation could obscure some speed differences:

You did read the line where we explained that storage is by _columns_ so
insertion by row _has to_ result in copies?

This too has been discussed before.  If performance matters, grow columns and
transose at the end.

Dirk

| 
| library(Rcpp)
| library(inline)
| 
| # fill a matrix by row with m0 rows and n0 columns
| row.code <- '
|    int m = Rcpp::as<int>(m0);
|    int n = Rcpp::as<int>(n0);
|    arma::mat mat = arma::zeros(m,n);
|    arma::rowvec vec = Rcpp::as<arma::rowvec>(vec0);
|    for (int i = 0; i < m; i++) {
|       mat.row(i) = vec;
|    }
|    return Rcpp::wrap(mat);
| '
| row.f <- cxxfunction(signature(m0="integer",n0="integer",vec0=
| "numeric"),row.code,plugin="RcppArmadillo")
| 
| # so here we swap, fill by column, m0 is the number of columns and n0 is the
| number of rows
| col.code <- '
|    int m = Rcpp::as<int>(m0);
|    int n = Rcpp::as<int>(n0);
|    arma::mat mat = arma::zeros(n,m);
|    arma::colvec vec = Rcpp::as<arma::colvec>(vec0);
|    for (int i = 0; i < m; i++) {
|       mat.col(i) = vec;
|    }
|    return Rcpp::wrap(mat);
| '
| col.f <- cxxfunction(signature(m0="
| integer",n0="integer",vec0="numeric"),col.code,plugin="RcppArmadillo")
| 
| > m <- 1e7
| > n <- 10
| > vec0 <- seq_len(n)
| > system.time({row.f(m,n,vec0)})
|    user  system elapsed
|   0.779   1.022   1.801
| > system.time({col.f(m,n,vec0)})
|    user  system elapsed
|   0.957   0.966   1.922
| > all.equal(row.f(m,n,vec0), t(col.f(m,n,vec0)))
| [1] TRUE
| 
| > m <- 1e6
| > n <- 100
| > vec0 <- seq_len(n)
| > system.time({row.f(m,n,vec0)})
|    user  system elapsed
|   1.925   1.425   3.351
| > system.time({col.f(m,n,vec0)})
|    user  system elapsed
|   1.244   1.423   2.667
| > all.equal(row.f(m,n,vec0), t(col.f(m,n,vec0)))
| [1] TRUE
| 
| 
| On Wed, Mar 27, 2013 at 9:44 AM, Conrad S <conradsand.arma at gmail.com> wrote:
| 
|     There's an even simpler way when using Armadillo, so that no loop is
|     required:
|     http://arma.sourceforge.net/docs.html#each_colrow
| 
|     For example:
| 
|     mat X(4,5);
|     rowvec r(5);
| 
|     X.each_row() = r;
| 
| 
|     (btw, in general it's more efficient to access matrices as columns
|     rather than rows).
| 
| 
|     On Wed, Mar 27, 2013 at 6:23 PM, Michael Love
|     <michaelisaiahlove at gmail.com> wrote:
|     > As recommended, I have switched to using Armadillo matrices, which
|     doesn't
|     > print out these lines.
|     > ...
|     > Example with Armadillo:
|     >
|     > arma.code <- '
|     >    arma::mat mat = Rcpp::as<arma::mat>(mat0);
|     >    arma::rowvec vec = Rcpp::as<arma::rowvec>(vec0);
|     >    for (int i = 0; i < mat.n_rows; i++) {
|     >       mat.row(i) = vec;
|     >    }
|     >    return Rcpp::wrap(mat);
|     > '
|     > arma.f <-
|     > cxxfunction(signature(mat0="numeric",vec0="numeric"),arma.code,plugin=
|     "RcppArmadillo")
|     > arma.f(mat0,vec0)
| 
| 
| 
| ----------------------------------------------------------------------
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
-- 
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com  


More information about the Rcpp-devel mailing list