データサイエ「ソ」ティストは語る

データサイエンティストではない、パチもんのデータサイエ「ソ」ティストのブログ

OpenBLASによるRの高速化(CentOS 6.5)

環境

  • CentOS 6.5 (Software Development Workstation) on VirtualBox 4.3.12
    • CPU: 4コア
    • メモリ: 4GB
    • HDD: 40GB
  • OpenBLAS: v0.2.11-0
  • R 3.1.1(オリジナル): yumでepelレポジトリからインストール
  • R 3.1.1(OpenBLAS版): srpmのspecファイルを使ってビルド

手順

基本的なLinuxの操作などが前提知識。

R(オリジナル)のインストール

epelレポジトリを使えるように設定して、yumでインストールする。

yum install R R-core

オリジナル版のベンチマーク

OpenBLAS と ATLAS の性能を R 上で比較する | 永田 晴久 下部のスクリプトを、適当な名前で保存する。

 set.seed(0)
 T <- 5
 N <- 2000
 A <- matrix(rnorm(N * N), N, N)
  
 ## Matrix multiplication
 t1 <- sapply(1 : T, function(t) system.time(A %*% A)['elapsed'])
  
 ## Matrix inversion
 t2 <- sapply(1 : T, function(t) system.time(solve(A))['elapsed'])
  
 ## Eigenvalues/vectors
 t3 <- sapply(1 : T, function(t) system.time(eigen(A))['elapsed'])
  
 ## Linear regression
 D <- as.data.frame(A)
 t4 <- sapply(1 : T, function(t) system.time(lm(V1 ~ ., data=D))['elapsed'])
  
 time <- cbind(t1, t2, t3, t4)
 besttime <- apply(time, 2, min)
 print(besttime)  # Print results

例えばspeedtest.Rとして保存し、バッチモードで実行する。

 R CMD BATCH --vanilla --slave speedtest.R

結果はspeedtest.Routに保存されているので、表示して確認する。

R 3.1.1(オリジナル)の測定結果

t1からt4はそれぞれ、行列積、逆行列の計算、固有値計算、線形回帰(参考サイトより)の最良値(単位は秒)。

t1 t2 t3 t4
5.604 6.476 39.215 4.396

R 3.1.1(オリジナル)のアンインストール

今回の方法ではバージョン番号など変えていないので、yumでインストールしたバイナリのRと、自分でビルドしたRが共存できない。なので、ビルドしたRをインストールする前に、バイナリのRをアンインストールしておく。

 yum -y remove libR*
 rpm -qa | grep "^R-" | xargs yum -y remove

OpenBLASのダウンロードとインストール

適当なディレクトリにOpenBLAS Homepage から最新版(v0.2.11-0)をダウンロードする。あとは、展開してmake、make install。

 tar xzvf xianyi-OpenBLAS-v0.2.11-0-ga7126c2.tar.gz
 cd xianyi-OpenBLAS-ea8d4e3/
 export OPENBLAS_NUM_THREADS=4
 export GOTO_NUM_THREADS=4
 export OMP_NUM_THREADS=4
 export OPENBLAS_MAIN_FREE=1
 NO_AFFINITY=1 make
 make install

デフォルトでは /opt/OpanBLAS 以下にインストールされる。

OpenBLASへのパス(?)を通す

/etc/ld.so.conf.d 以下にOpenBLAS.confとか適当な名前で以下の1行からなるファイルを作る

 /opt/OpenBLAS/lib

R 3.1.1のソース(srpm)をダウンロード

yum-utilsパッケージがインストールされていれば、以下のコマンドでR 3.1.1のsrpmファイルがダウンロードできる。

 yumdownloader --source R

ダウンロードしたsrpmファイルをインストールすると、ホームディレクトリにrpmbuildディレクトリができて、その中にファイルが展開される。

 rpm -ivh R-3.1.1-3.el6.src.rpm

specファイルの編集

rpmbuild/SPECSディレクトリにR.specファイルがあるので、以下のように編集する。

 --- R.spec.org	2014-08-08 21:52:38.000000000 +0900
 +++ R.spec	2014-10-11 16:55:35.706462019 +0900
 @@ -384,6 +384,9 @@
      --with-lapack \
      --with-blas \
  %endif
 +    --enable-BLAS-shlib \
 +    --with-lapack \
 +    --with-blas="openblas" \
      --with-tcl-config=%{_libdir}/tclConfig.sh \
      --with-tk-config=%{_libdir}/tkConfig.sh \
      --enable-R-shlib \
 @@ -477,7 +480,7 @@
  popd
  
  %check
 -make check
 +#make check
  
  %files
  # Metapackage

なお、make checkをコメントアウトしたのは、コンパイル後の各種テストの段階で、reg-BLAS.Rというファイルの実行に必ず失敗するため。LAPACK絡みっぽいが、オフィシャルなドキュメントやBugzillaにも挙がっているので無視してよいような。

rpmのビルド

R.specファイルがあるディレクトリで以下のようにコマンドを実行すると、ビルドが始まる。足りないライブラリがあれば、適宜インストールする。

 rpmbuild -ba R.spec

そこそこ時間がかかるので、待つ。

R 3.1.1(OpenBLAS版)のインストール

rpmbuild/RPMS/x86_64以下にrpmファイルができあがっているので、まとめてインストールする。

 pwd
 /root/rpmbuild/RPMS/x86_64
 
 rpm -Uvh R-3.1.1-3.el6.x86_64.rpm R-core-3.1.1-3.el6.x86_64.rpm \
          R-core-devel-3.1.1-3.el6.x86_64.rpm R-devel-3.1.1-3.el6.x86_64.rpm \
          R-java-3.1.1-3.el6.x86_64.rpm R-java-devel-3.1.1-3.el6.x86_64.rpm \
          libRmath-3.1.1-3.el6.x86_64.rpm libRmath-devel-3.1.1-3.el6.x86_64.rpm 

libRblas.soの差し替え

インストールしたあと、libRblas.soをOpenBLASのライブラリに差し替える。

 cd /usr/lib64/R/lib
 mv libRblas.so libRblas.so.org
 ln -s /opt/OpenBLAS/lib/libopenblas.so libRblas.so

(追記)LD_PRELOAD変数での切り替え

ライブラリをリネームしなくても、LD_PRELOAD変数を使うことで、オリジナルのlibRblas.soとOpenBLAS版のlibRblas.soを切り替えて使用できる。

 cd /opt/OpenBLAS/lib
 ln -s libopenblas.so libRblas.so
 ...
 export LD_PRELOAD="/opt/OpenBLAS/lib/libRblas.so"
 R

OpenBLAS版のベンチマーク

同じスクリプトを用いて、バッチモードで計測する。

  • オリジナル
t1 t2 t3 t4
5.604 6.476 39.215 4.396
  • OpenBLAS版
t1 t2 t3 t4
0.330 0.495 11.802 3.359

結果

f:id:data_sciesotist:20141011180157p:plain
f:id:data_sciesotist:20141011180042p:plain

実行時、CPUが複数使用されていることがわかる。また、実際の処理速度も向上している。もちろん、何でもかんでも並列化されるわけではなく、OpenBLASに処理が渡る部分が少ないと効果も薄いのだけど、Rのパッケージやコーディングレベルでの高速化とはまた違う、数値計算ライブラリをチューニングするという観点で、何か参考になれば。

Windows版Rにおける高速化

Windows版Rでは、CRANでATLASを用いたRblas.dllが公開されている。http://cran.ism.ac.jp/bin/windows/contrib/ATLAS/C2i7/のRblas.dllを、Rインストールディレクトリ\i386フォルダの中の同名ファイルに上書きする(念のためリネームしておいてもよい)。

また、GotoBLAS版も公開されている。http://prs.ism.ac.jp/~nakama/SurviveGotoBLAS2/binary/windows/

それだけで、(少なくとも今回使用しているベンチマークスクリプトにおいては)性能が向上する。以下はGotoBLASを使った場合。

  • オリジナル
 source("speedtest.R")
 besttime
    t1    t2    t3    t4 
  5.32  5.60 31.57  4.48
  • Rblas.dllの差し替え後
 source("speedtest.R")
 besttime
    t1    t2    t3    t4 
  0.30  0.65 38.91 20.61