简体   繁体   中英

How to apply lgamma to a matrix using Rcpp (and will it be faster)?

I am wondering if I can apply lgamma on all entries of a large matrix using Rcpp. I tried using a vector:

// lgammaRcpp.cpp
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector lgammaRcpp(NumericVector v){
    NumericVector out;
    out = lgamma(v);
    return(out);
}

I did a simple microbenchmarking:

library("microbenchmark")
x <- round(runif(100000)+50000);
microbenchmark(
   lgammaRcpp(x),
   lgamma(x)
)

and the Rcpp is slightly faster:

Unit: milliseconds
          expr      min       lq     mean   median       uq      max neval
 lgammaRcpp(x) 5.405556 5.416283 5.810254 5.436139 5.511993 8.650419   100    
     lgamma(x) 5.613717 5.628769 6.114942 5.644215 6.872677 9.947497   100

When I try using a "NumericMatrix", however:

// [[Rcpp::export]]
NumericMatrix lgammaRcpp(NumericMatrix v){
    NumericMatrix out;
    out = lgamma(v);
    return(out);
}

there are errors that I don't understand, eg

/home/canghel/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include/Rcpp/vector   /Matrix.h:83:13: note: Rcpp::Matrix<RTYPE, StoragePolicy>& Rcpp::Matrix<RTYPE, StoragePolicy>::operator=(const Rcpp::Matrix<RTYPE, StoragePolicy>&) [with int RTYPE = 14; StoragePolicy = Rcpp::PreserveStorage]
 Matrix& operator=(const Matrix& other) {

My questions are: 1) Is there a way to modify my function to apply lgamma over all entries to a matrix? and 2) Is it worth it, or is the underlying library that is called for the lgamma function the same for C++ and R?

It seems better (ie faster) to apply functions like lgamma/digamma to a matrix using the Rfast package.

library("microbenchmark");
library("RcppArmadillo");
library("Rfast");
sourceCpp("lgammaRcpp.cpp");

x <- matrix(round(runif(100000)+50000), 100, 1000);
microbenchmark(
    lgammaRcpp(x),
    lgamma(x),
    Rfast::Lgamma(x)
)
Unit: milliseconds
          expr      min       lq     mean   median       uq      max neval
lgammaRcppArma(x) 4.654526 4.919831 5.577843 5.413790 5.888895 9.258325   100
lgamma(x) 5.572671 5.840268 6.582007 6.131651 7.280895 8.779301   100
Rfast::Lgamma(x) 4.450824 4.588596 5.128323 4.791287 5.608678 6.865331   100

where I had:

#include<RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::mat lgammaRcpp(arma::mat m) {
    arma::mat out = lgamma(m);
    return(out);
}
  1. Rcpp Sugar tends to return Vectors unless otherwise specified. Thus, you will always get back in this case a Vector of type Numeric eg NumericVector . See my notes on different sugar functions here: https://github.com/coatless/rcpp-api

The following allows for a compilation under the above note:

#include <Rcpp.h>

// [[Rcpp::export]]
NumericVector lgammaRcpp(NumericMatrix v) { 
    NumericVector out;
    out = lgamma(v);
    return(out);
}
  1. It is highly unlikely you will see a large speed up as the functions being used are the same. This is partially indicated with your above benchmarks and can be verified by looking at Rcpp Math defines . Now, this isn't to say a benefit is not available. In particular, the main benefit here is if you are encapsulating a routine completely in C++. In which case, your routine will be significantly quicker if you use Sugar functions if compared to calling an R function from C++ .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM