Recently, I went to the 23th STSC, I got some information about the new API of Rcpp, Rcpp attributes. I had tried some examples and it worked well. Here I demonstrate some examples.
Rcpp attributes allows user to write Rcpp in a simple way. User does not need to learn about how to write R extension. Just write a cpp script and add the line // [[Rcpp::export]], then user can use the function in R.
Next two example is about the two extension packages of Rcpp, RcppArmadillo and RcppEigen. The two packages provide Rcpp to link the C++ linear algebra libraries, armadillo and Eigen.
library(Rcpp) library(RcppArmadillo) library(RcppEigen) sourceCpp(code = ' // [[Rcpp::depends(RcppArmadillo)]] #include <RcppArmadillo.h> using namespace Rcpp; // [[Rcpp::export]] List fastLm_RcppArma(NumericVector yr, NumericMatrix Xr) { int n = Xr.nrow(), k = Xr.ncol(); arma::mat X(Xr.begin(), n, k, false); arma::colvec y(yr.begin(), yr.size(), false); arma::colvec coef = arma::solve(X, y); arma::colvec resid = y - X*coef; double sig2 = arma::as_scalar(arma::trans(resid)*resid/(n-k)); arma::colvec stderrest = arma::sqrt(sig2 * arma::diagvec( arma::inv(arma::trans(X)*X))); return List::create( Named("coefficients") = coef, Named("stderr") = stderrest); }')
sourceCpp(code = ' // [[Rcpp::depends(RcppEigen)]] #include <RcppEigen.h> using namespace Rcpp; using Eigen::Map; using Eigen::MatrixXd; using Eigen::VectorXd; // [[Rcpp::export]] List fastLm_RcppEigen(NumericVector yr, NumericMatrix Xr) { const Map<MatrixXd> X(as<Map<MatrixXd> >(Xr)); const Map<VectorXd> y(as<Map<VectorXd> >(yr)); int n = Xr.nrow(), k = Xr.ncol(); VectorXd coef = (X.transpose() * X).llt().solve(X.transpose() * y.col(0)); VectorXd resid = y - X*coef; double sig2 = resid.squaredNorm() / (n - k); VectorXd stderrest = (sig2 * ((X.transpose() * X).inverse()).diagonal()).array().sqrt(); return List::create( Named("coefficients") = coef, Named("stderr") = stderrest); }') N = 20000 p = 1000 X = matrix(rnorm(N*p), ncol = p) y = X %*% 10**(sample(seq(-5, 3, length = N+p), p)) + rnorm(N)
system.time(fastLm_RcppArma(y, X)) # user system elapsed # 5.49 0.06 1.46 system.time(fastLm_RcppEigen(y, X)) # user system elapsed # 9.32 0.06 8.96 system.time(lm(y~X - 1)) # user system elapsed # 145.13 14.76 91.84
The cpp functions are faster 63 times than R function lm. My environment is ubuntu 14.04, R 3.1.1 compiled by intel c++, fortran compiler with MKL. My CPU is 3770K@4.3GHz. I think that Rcpp is the package which is the worthiest to learn if you want to use R to do statistical computing or machine learning. Rcpp attributes had changed the way to source C++ code in R, it let Rcpp is more convenient and more powerful.
This post is used to record some tips I can’t categorize in ubuntu.
i. automatically load some shell scripts In my system ubuntu 14.04, I can find the file .bashrc in my home directory. Since I want ubuntu to load intel complier and mkl parameter automatically, all I need to do is to add the two lines in the end of that file: (mint 17: gedit /etc/bash.bashrc)
sudo -s source /opt/intel/composer_xe_2013_sp1.3.174/mkl/bin/mklvars.sh intel64 source /opt/intel/composer_xe_2013_sp1.3.174/bin/compilervars.sh intel64 cd numpy # rm -rf build # if there is a build folder subl site.cfg
/* sublime-imfix.c Use LD_PRELOAD to interpose some function to fix sublime input method support for linux. By Cjacker Huang gcc -shared -o libsublime-imfix.so sublime-imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC LD_PRELOAD=./libsublime-imfix.so subl */ #include<gtk/gtk.h> #include<gdk/gdkx.h> typedef GdkSegment GdkRegionBox;
struct _GdkRegion { long size; long numRects; GdkRegionBox *rects; GdkRegionBox extents; };
rectangle->x = region->extents.x1; rectangle->y = region->extents.y1; rectangle->width = region->extents.x2 - region->extents.x1; rectangle->height = region->extents.y2 - region->extents.y1; GdkRectangle rect; rect.x = rectangle->x; rect.y = rectangle->y; rect.width = 0; rect.height = rectangle->height; //The caret width is 2; //Maybe sometimes we will make a mistake, but for most of the time, it should be the caret. if(rectangle->width == 2 && GTK_IS_IM_CONTEXT(local_context)) { gtk_im_context_set_cursor_location(local_context, rectangle); } }
//this is needed, for example, if you input something in file dialog and return back the edit area //context will lost, so here we set it again.
R Benchmark 2.5 =============== Number of times each test is run__________________________: 3
I. Matrix calculation --------------------- Creation, transp., deformation of a 2500x2500 matrix (sec): 0.812333333333334 2400x2400 normal distributed random matrix ^1000____ (sec): 0.474666666666667 Sorting of 7,000,000 random values__________________ (sec): 0.563333333333333 2800x2800 cross-product matrix (b = a' * a)_________ (sec): 8.99466666666667 Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec): 4.42166666666667 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 1.26481956425649
II. Matrix functions -------------------- FFT over 2,400,000 random values____________________ (sec): 0.396000000000001 Eigenvalues of a 640x640 random matrix______________ (sec): 0.718000000000001 Determinant of a 2500x2500 random matrix____________ (sec): 3.03633333333334 Cholesky decomposition of a 3000x3000 matrix________ (sec): 3.42433333333333 Inverse of a 1600x1600 random matrix________________ (sec): 2.56266666666666 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 1.77441555997029
III. Programmation ------------------ 3,500,000 Fibonacci numbers calculation (vector calc)(sec): 0.543999999999992 Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec): 0.294333333333337 Grand common divisors of 400,000 pairs (recursion)__ (sec): 0.686666666666658 Creation of a 500x500 Toeplitz matrix (loops)_______ (sec): 0.49266666666666 Escoufier's method on a 45x45 matrix (mixed)________ (sec): 0.378999999999991 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.466584631384852 Total time for all 15 tests_________________________ (sec): 27.8006666666666 Overall mean (sum of I, II and III trimmed means/3)_ (sec): 1.01548017027814 --- End of test ---
R Benchmark 2.5 =============== Number of times each test is run__________________________: 3
I. Matrix calculation --------------------- Creation, transp., deformation of a 2500x2500 matrix (sec): 0.755666666666667 2400x2400 normal distributed random matrix ^1000____ (sec): 0.473 Sorting of 7,000,000 random values__________________ (sec): 0.572 2800x2800 cross-product matrix (b = a' * a)_________ (sec): 0.411 Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec): 0.213 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.480875883392325
II. Matrix functions -------------------- FFT over 2,400,000 random values____________________ (sec): 0.372666666666666 Eigenvalues of a 640x640 random matrix______________ (sec): 0.895 Determinant of a 2500x2500 random matrix____________ (sec): 0.271333333333335 Cholesky decomposition of a 3000x3000 matrix________ (sec): 0.243333333333333 Inverse of a 1600x1600 random matrix________________ (sec): 0.328000000000001 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.321291459145567
III. Programmation ------------------ 3,500,000 Fibonacci numbers calculation (vector calc)(sec): 0.522333333333335 Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec): 0.259666666666668 Grand common divisors of 400,000 pairs (recursion)__ (sec): 0.674333333333337 Creation of a 500x500 Toeplitz matrix (loops)_______ (sec): 0.499333333333335 Escoufier's method on a 45x45 matrix (mixed)________ (sec): 0.352999999999994 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.451548428599678 Total time for all 15 tests_________________________ (sec): 6.84366666666667 Overall mean (sum of I, II and III trimmed means/3)_ (sec): 0.411666478563312 --- End of test ---
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz tar -xvzf libiconv-1.14.tar.gz cd libiconv-1.14 && ./configure --prefix=/usr/local/libiconv make && sudo make install
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
修改後的scipt:
1 2 3
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16) _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); #endif
之後再重新make就成功了。
取得R source code:
1 2
wget http://cran.csie.ntu.edu.tw/src/base/R-3/R-3.2.3.tar.gz tar -xvzf R-3.2.3.tar.gz
取得Intel C++ compiler and Intel MKL,你可以取得non-commercial license for this two software in intel website. 另外,64bit linux system不支援32 bits的compiler,安裝時記得取消掉IA32的安裝。
make && make check # removing R before installation rm /usr/lib/libR.so rm -r /usr/lib/R rm -r /usr/bin/Rscript rm -r /usr/local/lib/R make docs make install chown -R celest.celest /usr/local/lib/R chmod -R 775 /usr/local/lib/R # to add mkl and intel c compiler into path echo'source /opt/intel/composer_xe_2015/mkl/bin/mklvars.sh intel64' >> /etc/bash.bashrc echo'source /opt/intel/composer_xe_2015/bin/compilervars.sh intel64' >> /etc/bash.bashrc exit # install required package R -e "install.packages('SuppDists', repos = 'http://cran.rstudio.com/')" # run benchmark R -e "source('http://r.research.att.com/benchmarks/R-benchmark-25.R')" # to run rstudio-server, you have two options, first: # echo 'rsession-which-r=/usr/local/bin/R' >> /etc/rstudio/rserver.conf # second , please use option configure with --prefix=/usr
R Benchmark 2.5 =============== Number of times each test is run__________________________: 3
I. Matrix calculation --------------------- Creation, transp., deformation of a 2500x2500 matrix (sec): 0.683 2400x2400 normal distributed random matrix ^1000____ (sec): 0.259666666666667 Sorting of 7,000,000 random values__________________ (sec): 0.560333333333333 2800x2800 cross-product matrix (b = a' * a)_________ (sec): 0.44 Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec): 0.193666666666666 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.400041560496478
II. Matrix functions -------------------- FFT over 2,400,000 random values____________________ (sec): 0.393666666666667 Eigenvalues of a 640x640 random matrix______________ (sec): 0.326999999999999 Determinant of a 2500x2500 random matrix____________ (sec): 0.215666666666666 Cholesky decomposition of a 3000x3000 matrix________ (sec): 0.183999999999999 Inverse of a 1600x1600 random matrix________________ (sec): 0.182333333333332 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.234990082575285
III. Programmation ------------------ 3,500,000 Fibonacci numbers calculation (vector calc)(sec): 0.274333333333333 Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec): 0.221333333333333 Grand common divisors of 400,000 pairs (recursion)__ (sec): 0.275666666666667 Creation of a 500x500 Toeplitz matrix (loops)_______ (sec): 0.255 Escoufier's method on a 45x45 matrix (mixed)________ (sec): 0.338999999999999 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.268164327390206 Total time for all 15 tests_________________________ (sec): 4.80466666666666 Overall mean (sum of I, II and III trimmed means/3)_ (sec): 0.293214347493761 --- End of test ---
最後只需要用到4.8秒就可以完成了,可是complitation過程是滿麻煩的,雖然參考了多個網站,可是參數的設定都不太一樣,linux又有權限的限制,而且就算編譯成功,Rcpp這個套件不見得能夠成功,因此花了很久才終於編譯成功,並且能夠直接開啟,只是要利用到c, cpp or fortran時還是需要source compilervars.sh才能夠運行,而且我安裝了三四十個套件都沒有問題了。最後,如果沒有特別要求速度下,其實直接用OpenBLAS就可以省下很多麻煩。另外,我做了一個小小的測試於Rcpp上,速度有不少的提昇(因為用intel C++ compiler,大概增加5~10倍),測試結果就不放上來了。以上資訊供大家參考,轉載請註明來源,謝謝。
最後附上測試環境: My environment is mint 17.3, R 3.2.3 compiled by Intel c++, fortran compiler with Intel MKL. My CPU is 3770K@4.4GHz.
To use the html help page and change the default language of R to english, you can do that: