Hi guys, I'm trying to use Rcpp to implement an 'apply'-type function for matrices, whereby I apply a function to each row or column of a matrix. I'm testing it here with the 'mean' just to see how well we can do vs. the highly optimized rowMeans, colMeans functions, but of course any other function taking a vector and returning a scalar might fit here. I'm wondering if I can do better. Please see the gist in the link here; you can sourceCpp it in R. https://gist.github.com/4561281 I try to limit the amount of copying as much as possible with NumericMatrix::Column and NumericMatrix::Row. Note that the Rcpp solution over columns is just as fast as colMeans, but over rows it's a fair bit slower relative to rowMeans. Is there any way I could improve this? I plan to submit an expanded version of this to the Rcpp gallery so any advice is appreciated! Thanks, -Kevin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130117/6a3d2b6a/attachment.html>
[Rcpp-devel] Most efficient way to apply function over rows of a matrix with Rcpp?
4 messages · Dirk Eddelbuettel, Kevin Ushey, Romain Francois
Hi Kevin, First off, congrats regarding RcppRool. Nice to see another package on CRAN. I had some follow-up questions as to whether you planned to push this further: the mean at n+1 is really just adding 1/n of the difference between the newest and the oldest... but getting these things right is hard. Anyway, I didn't really have time poke around so consider these questions not asked :)
On 17 January 2013 at 18:09, Kevin Ushey wrote:
| Hi guys, | | I'm trying to use Rcpp to implement an 'apply'-type function for matrices, | whereby I apply a function to each row or column of a matrix. I'm testing it | here with the 'mean' just to see how well we can do vs. the highly optimized | rowMeans, colMeans functions, but of course any other function taking a vector | and returning a scalar might fit here. | | I'm wondering if I can do better. Please see the gist in the link here; you can | sourceCpp it in R. | | https://gist.github.com/4561281 | | I try to limit the amount of copying as much as possible with | NumericMatrix::Column and NumericMatrix::Row. | | Note that the Rcpp solution over columns is just as fast as colMeans, but over | rows it's a fair bit slower relative to rowMeans. Is there any way I could | improve this? I never measured. I always stopped at the simple sapply/lapply implementations I showed in the talks/workshops. One problem is column-wise storage of vectors. For kicks, can you see what happens when for rowMeans you do a transpose and then compute colMeans ? | I plan to submit an expanded version of this to the Rcpp gallery so any advice | is appreciated! That;s the spirit -- let's grow http://gallery.Rcpp.org which is meant to be open for contributions. Cheers, Dirk
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
On Thu, Jan 17, 2013 at 7:25 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
Hi Kevin, First off, congrats regarding RcppRool. Nice to see another package on CRAN. I had some follow-up questions as to whether you planned to push this further: the mean at n+1 is really just adding 1/n of the difference between the newest and the oldest... but getting these things right is hard. Anyway, I didn't really have time poke around so consider these questions not asked :)
Thanks! I do plan on extending the package further, but I need to iron out some of the bugs and makes the pseudo-API available within more accessible first. I'm definitely open to new ideas / additions though.
On 17 January 2013 at 18:09, Kevin Ushey wrote: | Hi guys, | | I'm trying to use Rcpp to implement an 'apply'-type function for matrices, | whereby I apply a function to each row or column of a matrix. I'm testing it | here with the 'mean' just to see how well we can do vs. the highly optimized | rowMeans, colMeans functions, but of course any other function taking a vector | and returning a scalar might fit here. | | I'm wondering if I can do better. Please see the gist in the link here; you can | sourceCpp it in R. | | https://gist.github.com/4561281 | | I try to limit the amount of copying as much as possible with | NumericMatrix::Column and NumericMatrix::Row. | | Note that the Rcpp solution over columns is just as fast as colMeans, but over | rows it's a fair bit slower relative to rowMeans. Is there any way I could | improve this? I never measured. I always stopped at the simple sapply/lapply implementations I showed in the talks/workshops. One problem is column-wise storage of vectors. For kicks, can you see what happens when for rowMeans you do a transpose and then compute colMeans ?
It's still faster to just compute the rowMeans compared to column means on the transpose, for different sizes of matrices... Interestingly though, the Rcpp rowMeans actually runs faster (!) than base-R rowMeans for a matrix w/ 1E4 rows, 1E2 columns, so the relative speed does depend on the size / shape of the matrix. I'm always a little surprised to learn these things. Regardless, an Rcpp 'apply' solution is almost always faster than the corresponding R 'apply' solution.
| I plan to submit an expanded version of this to the Rcpp gallery so any advice | is appreciated! That;s the spirit -- let's grow http://gallery.Rcpp.org which is meant to be open for contributions.
I will have something nifty to submit tomorrow. :)
Cheers, Dirk -- Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130117/eb491f5a/attachment-0001.html>
12 days later
Le 18/01/13 03:09, Kevin Ushey a ?crit :
Hi guys, I'm trying to use Rcpp to implement an 'apply'-type function for matrices, whereby I apply a function to each row or column of a matrix. I'm testing it here with the 'mean' just to see how well we can do vs. the highly optimized rowMeans, colMeans functions, but of course any other function taking a vector and returning a scalar might fit here. I'm wondering if I can do better. Please see the gist in the link here; you can sourceCpp it in R. https://gist.github.com/4561281 I try to limit the amount of copying as much as possible with NumericMatrix::Column and NumericMatrix::Row. Note that the Rcpp solution over columns is just as fast as colMeans, but over rows it's a fair bit slower relative to rowMeans. Is there any way I could improve this? I plan to submit an expanded version of this to the Rcpp gallery so any advice is appreciated! Thanks, -Kevin
The use of the NumericMatrix::Row has some cost, each time we access
tmp[i], we must calculate the right offset :
inline int offset( int i, int j) const { return i + nrows * j ; }
You could implement it yourself taking into account the structure of the
matrix:
// [[Rcpp::export]]
NumericVector row_means_2( NumericMatrix& X ) {
int nRows = X.nrow(), nCols = X.ncol() ;
NumericVector out = no_init(nRows);
for( int j=0, k=0; j < nCols; j++ ) {
for( int i=0; i < nRows; i++, k++ ) {
out[i] += X[k] ;
}
}
for( int i =0; i<nRows; i++) out[i] /= nCols ;
return out;
}
With this I get:
> benchmark(replications = 5, order = NULL, apply(x,
+ 1, mean), rowMeans(x), row_means(x), row_means_2(x))
test replications elapsed relative user.self sys.self
1 apply(x, 1, mean) 5 0.266 24.181818 0.253 0.013
2 rowMeans(x) 5 0.012 1.090909 0.011 0.000
3 row_means(x) 5 0.041 3.727273 0.041 0.000
4 row_means_2(x) 5 0.011 1.000000 0.011 0.000
user.child sys.child
1 0 0
2 0 0
3 0 0
4 0 0
Maybe there is something we can do at our end to improve this by making
a more efficient iterator over a matrix row.
Romain
Romain Francois Professional R Enthusiast +33(0) 6 28 91 30 30 R Graph Gallery: http://gallery.r-enthusiasts.com blog: http://romainfrancois.blog.free.fr |- http://bit.ly/RE6sYH : OOP with Rcpp modules `- http://bit.ly/Thw7IK : Rcpp modules more flexible