MacOS版R4.0にOpenBLASをリンクさせる
以前からRの高速化については少し興味があって,この記事を見て割合簡単にできそうだなと思い試してみた記録です. 結論から言うと,自分の環境上ではデフォルトのBLASからOpenBLASに切り替えたところ,ベンチマークでは3~8倍程度高速化しました.特に行列計算での向上が大きく寄与していました.
Rを含めてhomebrewでパッケージ管理をしているのですが,OpenblasとRのリンクについてはbrew単独ではうまくいかなかったのでまとめてみます1.
環境
- OS: MacOS Catalina 10.15.5
$ system_profiler SPHardwareDataType Hardware: Hardware Overview: Model Name: MacBook Air Model Identifier: MacBookAir9,1 Processor Name: Quad-Core Intel Core i5 Processor Speed: 1.1 GHz Number of Processors: 1 Total Number of Cores: 4 L2 Cache (per Core): 512 KB L3 Cache: 6 MB Hyper-Threading Technology: Enabled Memory: 16 GB
- R: 4.0.3
homebrewの導入などは省略します.
準備(インストールするもの)
- gcc:OpenBLASのコンパイル用です.Rをbrew経由で入れている場合は既にインストールされていると思います.
brew install gcc
で入れてください. - openblas: こちらもbrewから入れることができます.
--build-from-source
のオプションを付けてソースからビルドしない場合,最適化されないようなので注意してください. - ベンチマークスクリプト: R-benchmark-25.Rを用います.乱数生成に際して
SuppDists
ライブラリが必要ですが,スクリプト内のコメントのように標準の乱数生成関数に変更することもできます.
速度比較
RがリンクしているBLASを確かめる際の手順はこちらの記事を参照してください.
標準BLASの結果
❯ cat R-benchmark-25.R | time R --slave R Benchmark 2.5 =============== Number of times each test is run__________________________: 3 I. Matrix calculation --------------------- Creation, transp., deformation of a 2500x2500 matrix (sec): 0.545666666666667 2400x2400 normal distributed random matrix ^1000____ (sec): 0.176 Sorting of 7,000,000 random values__________________ (sec): 0.836999999999999 2800x2800 cross-product matrix (b = a' * a)_________ (sec): 18.3796666666667 Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec): 9.76233333333334 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 1.64589517363295 II. Matrix functions -------------------- FFT over 2,400,000 random values____________________ (sec): 0.272333333333331 Eigenvalues of a 640x640 random matrix______________ (sec): 0.989333333333339 Determinant of a 2500x2500 random matrix____________ (sec): 3.89733333333334 Cholesky decomposition of a 3000x3000 matrix________ (sec): 6.442 Inverse of a 1600x1600 random matrix________________ (sec): 4.22166666666666 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 2.53433902483476 III. Programmation ------------------ 3,500,000 Fibonacci numbers calculation (vector calc)(sec): 0.224666666666659 Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec): 0.214666666666668 Grand common divisors of 400,000 pairs (recursion)__ (sec): 0.309333333333323 Creation of a 500x500 Toeplitz matrix (loops)_______ (sec): 0.0759999999999934 Escoufier's method on a 45x45 matrix (mixed)________ (sec): 0.60899999999998 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.246174647838452 Total time for all 15 tests_________________________ (sec): 46.957 Overall mean (sum of I, II and III trimmed means/3)_ (sec): 1.00887354980068 --- End of test --- R --slave 221.80s user 2.71s system 99% cpu 3:46.49 total
OpenBLASに切り替え
上の記事に従って標準BLASのパスを確認したあとに,brew経由でインストールしたOpenBLASにリンクを張り替えます
$ ln -sf /usr/local/opt/openblas/lib/libopenblas.dylib /usr/local/Cellar/r/4.0.3/lib/R/lib/libRblas.dylib
- 多くの記事では
brew install r --with-openblas
としていますが,2020/10/24現在だとinvaid option
のエラーが発生します.今回はシンボリックリンクを張り替えることで対応しました.
OpenBLASの結果
OpenBLASを使用したRの性能を見てみましょう:
❯ cat R-benchmark-25.R | time R --slave R Benchmark 2.5 =============== Number of times each test is run__________________________: 3 I. Matrix calculation --------------------- Creation, transp., deformation of a 2500x2500 matrix (sec): 0.509333333333333 2400x2400 normal distributed random matrix ^1000____ (sec): 0.161 Sorting of 7,000,000 random values__________________ (sec): 0.967666666666667 2800x2800 cross-product matrix (b = a' * a)_________ (sec): 0.443666666666666 Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec): 0.273666666666667 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.395451840253713 II. Matrix functions -------------------- FFT over 2,400,000 random values____________________ (sec): 0.223333333333333 Eigenvalues of a 640x640 random matrix______________ (sec): 0.632666666666667 Determinant of a 2500x2500 random matrix____________ (sec): 0.285666666666666 Cholesky decomposition of a 3000x3000 matrix________ (sec): 0.38 Inverse of a 1600x1600 random matrix________________ (sec): 0.448333333333334 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.365102436446165 III. Programmation ------------------ 3,500,000 Fibonacci numbers calculation (vector calc)(sec): 0.253 Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec): 0.212333333333333 Grand common divisors of 400,000 pairs (recursion)__ (sec): 0.261333333333334 Creation of a 500x500 Toeplitz matrix (loops)_______ (sec): 0.0456666666666668 Escoufier's method on a 45x45 matrix (mixed)________ (sec): 0.247999999999998 -------------------------------------------- Trimmed geom. mean (2 extremes eliminated): 0.237062827419034 Total time for all 15 tests_________________________ (sec): 5.34566666666667 Overall mean (sum of I, II and III trimmed means/3)_ (sec): 0.324681290870627 --- End of test --- R --slave 62.53s user 4.91s system 191% cpu 35.241 total
行列演算が30~40倍,コレスキー分解なども10倍程度速くなっており,冒頭で挙げた記事とも整合的な結果が出ました.
homebrewは楽で良いのですが,設定の最適化をする際にはこうして面倒を見る必要があるなという印象です.
参考資料
- http://uncorrelated.hatenablog.com/entry/2020/10/13/164340
- https://qiita.com/hoxo_m/items/aa04b9d3d7a32cb6a1a3
- https://gist.github.com/cheuerde/a5e0701383bac688d465
-
後々確認するとRのdependencyにopenblasが含まれており全くの無駄記事を書いている気分になりましたが,私の環境では標準BLASの方にリンクされていたのでそういうパターンもあるようです.↩