简体   繁体   中英

Speed up RcppArmadillo: How to link to OpenBlas in an R package

I am working on an R package which uses RcppArmadillo. I am trying to take advantage of faster matrix multiplication found in OpenBLAS. In the documentation of the C++ armadillo library, it says if we have OpenBLAS on our machine then Armadillo would use OpenBLAS instead of BLAS. However, when I compile my R package, I get something like this:

g++ -m64 -std=c++11 -shared -L/usr/lib64/R/lib -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -o PackageTest.so class1.o class2.o class3.o class4.o class5.o class6.o class7.o RcppExports.o class8.o class9.o class10.o -L/usr/lib64/R/lib -lRlapack -L/usr/lib64/R/lib -lRblas -lgfortran -lm -lquadmath -L/usr/lib64/R/lib -lR

So it is compiling with the -lRlapack and -lRblas options. How can I properly modify the Makevars and Makevars.win files to have RcppArmadillo compile the package with the option -lopenblas ? My attempt to solve this problem was to modify the Makevars file in the following way:

PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_CXXFLAGS =-fopenmp -std=c++11 -lopenblas
PKG_CXX1XFLAGS = $(PKG_CXXFLAGS)

The package did compile with -lopenblas , but is this the best way to do it?

That is a problem with your RedHat installation which chose to rely on the internal LAPACK sources for R when installing R --- plus the fact that RcppArmadillo uses whatever R uses.

On my Debian/Ubuntu based machine, it happens differently. Ie for

R> library(Rcpp)
R> cppFunction("arma::mat foo(arma::mat x) { return x + x;} ", depends="RcppArmadillo", verbose=TRUE)

I get (inter alia)

g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions \
    -Wl,-z,relro -o sourceCpp_4.so file677111d81351.o \
    -fopenmp -llapack -lblas -lgfortran -lm -lquadmath \
    -L/usr/lib/R/lib -lR

and we see -llapack -lblas -lgfortran as expected.

Instructions for compiling R, OpenBLAS and linking R with OpenBLAS (GNU/Linux)

I believe your biggest problem is linking R to the OpenBLAS library. So the steps I write below can help you succeed in this link.

Compiling OpenBLAS

Initially download the R and OpenBLAS ( Open Optimized BLAS Library) source codes in OpenBLAS . In the file directory, perform the following steps.

tar -zxvf OpenBLAS*
cd OpenBLAs*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/

or

git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/

Note : This will make the compilation run faster using all the features of your CPU. To know the number of cores, do: nproc .

Compiling Armadillo C++ with OpenBLAS

For those who use C++ codes in R using the Rcpp library, setting up the Armadillo with the OpenBLAS library may be of some benefit.

tar -xvf armadillo*
cd armadillo*
./configure -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
cmake . -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
make -j $nproc
sudo make install

Note : Further details regarding the compilation of the Armadillo library can be found at https://gitlab.com/conradsnicta/armadillo-code .

Compiling R with OpenBLAS

After compiling OpenBLAS , download the R code. It is not necessary to compile R to make use of OpenBLAS , but compiling the language may bring some benefits that may be insignificant depending on what is being done in R . That way, download the source code of the language R .

Note : In my operating system, Arch Linux, OpenBLAS ) was installed in the /opt directory. Search for the OpenBLAS installation directory in your GNU/Linux distribution.

In the directory where the R was downloaded, do the following:

tar -zxvf R*
cd R-* && ./configure --enable-R-shlib --enable-threads=posix --with-blas="-lopenblas -L/opt/OpenBLAS/lib -I/opt/OpenBLAS/include -m64 -lpthread -lm"
make -j $nproc
sudo make install

Most likely the OpenBLAS library will be bound to R . To check, run in the R the sessionInfo() code. Something like the output below should appear:

Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so

If linking does not occur, follow the steps outlined in the code below.

We need to link the R with the file libopenblas_* , created in the process of compiling the library OpenBLAS . In my case, the file is ibopenblas_haswellp-r0.2.20.so . Look for this in /opt/OpenBLAS/lib or in the directory where OpenBLAS was installed on your GNU/Linux system. Also look for the libRblas.so file directory found in the R language installation directory. In Arch, this directory is /usr/local/lib64/R/lib .

cd /usr/local/lib64/R/lib
mv libRblas.so libRblas.so.keep
ln -s /opt/OpenBLAS/lib/libopenblas_haswellp-r0.2.20.so libRblas.so

Start a section of language R and do sessionInfo() . You should note something like:

Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so

To make use of multithreaded processing, do export OPENBLAS_NUM_THREADS=1 before starting a R section.

NOTE : For intel processors, sudo cpupower frequency-set -g performance , can boost performance. Read more at https://wiki.archlinux.org/index.php/CPU_frequency_scaling .

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