GPUアーキテクト&トレンドGPUアーキテクト&トレンド

ベンチマーク

「R」でGPUを使ってみた

2018.11.22

サービスクリエーション本部 GPUアーキテクト 森重 ゆう

サービスクリエーション本部
GPUアーキテクト
森重 ゆう

「R」でGPUを使ってみた

統計解析や機械学習の分野で多く使われているフリーソフト「R」は、基本的にシングルコアで動作するため、昨今のビックデータブームの中では「処理速度が遅い」と感じることが多くなってきました。

「R」を高速化させる手法には、forではなくapplyを使う、繰り返し処理はさせずベクトル演算を使う、といったコードの適正化から、snow packageでapplyを並列処理化するなどのR packageを使用する、などが挙げられます。これらは、繰り返し処理の部分がボトルネックだと考えて、高速化を図っている例です。
今回は、実際に計算をしている部分をGPUで並列処理させ、「R」の高速化を実現したいと思います。「R」でGPUを使う方法はいくつかあります。

- NVBLAS gputools gpuR
概要 GPUを使用する
BLASを実装する
GPUを使用する
新たな関数を実装する
GPUを使用する
新たな関数を実装する
インストール方法 CUDA®同梱 R package R package
GPU NVIDIA® NVIDIA® NVIDIA®、AMD®など
(openCLが動けば良い)

今回は、インストールが簡単でコードの書き換えが不要なNVBLASを使用します。

BLASとNVBLAS

本題に入る前に、BLAS ( Basic Linear Algebra Subprograms ) について説明します。
BLASは、基本的な線形演算のライブラリ、例えば行列やベクトルの基本的な計算を行う関数群です。
「R」にもBLASが使われているため、「BLASの高速化=Rの高速化」ということになります。主なBLAS高速化手法は、デフォルトのBLASからより速いBLASに置き換えることです。
BLASには、レベルがあり次のように分類されています。

レベル 内容 主な関数
Level 1 ベクトルとベクトルの演算 axpy_ ( ベクトルの加算 )
Level 2 行列とベクトルの演算 gemv_ ( 一般行列とベクトルの積 )
Level 3 行列と行列の演算 gemm_ ( 一般行列と一般行列の積 )

NVBLASはNVIDIA®が提供する、GPUによって高速化されるBLAS Level 3ルーティンを実装するBLASです。データ型はDouble型のみサポートしています。

したがって、高速化の恩恵をより多く享けるためには、Double型でLevel 3ルーティンを使うように、「R」のコードを工夫することが重要となります。

検証

では実際に、NVBLASを使用すれば「R」が高速化するのか検証してみたいと思います。

構成

サーバー

  • 筐体 : Supermicro® SYS-6019U-TR4
  • CPU : Intel® Xeon® Gold 6150 CPU @ 2.70GHz *
  • GPU : NVIDIA® Tesla® V100 16GB

OS / ソフトウェア

  • OS : Ubuntu 16.04.5 LTS
  • NVIDIA Driver : 396.44
  • CUDA : V9.0.176
  • R : 3.4.4

NVBLASの使用準備

CUDAの一部としてあるため、別途インストールする必要はありません。
「Rで」NVBLASを使用するためには、2つの手順が必要となります。

  1. 設定ファイルを作成する
    名前はなんでも良いですが、今回は/etc/nvblas.confという設定ファイルを作成します。今回は次の設定で作成しました。
    NVBLAS_LOGFILE nvblas.log
    NVBLAS_TRACE_LOG_ENABLED
    NVBLAS_CPU_BLAS_LIB /usr/lib/libblas.so
    NVBLAS_GPU_LIST ALL
    NVBLAS_TILE_DIM 2048
    NVBLAS_AUTOPIN_MEM_ENABLED
    重要な要素は、 NVBLAS_CPU_BLAS_LIB と NVBLAS_GPU_LIST です。
    • NVBLAS_CPU_BLAS_LIB
      ここではNVBLASが実装していない、BLAS Level 1, 2ルーティンを実装しているBLASを指定します。今回は、「R」のデフォルトのBLASを指定しています。
      「R」が現在使用しているBLAS、場所がわからないときはこの手順で調べられます。
      まず、ターミナルを開いて「R」 を実行します。
      別のターミナルで次を実行してpidを取得します。
      ps aux | grep exec/R
      
      pidが取得できたため、次を実⾏するとBLASと場所を確認できます。
      lsof -p <pid> | grep 'blas\|lapack'
      
    • NVBLAS_GPU_LIST
      ここでは使⽤する GPUを指定できます。
      今回は、⼀枚しかないためすべて使う設 定しました。
  2. 「R」起動時に環境変数を設定する
    LD_PRELOADとNVBLAS_CONFIG_FILEという変数を設定する必要があります。
    • LD_PRELOAD
      使用するNVBLASの場所を指定します。
      今回の環境ではここでした。
      /usr/local/cuda-9.0/lib64/libnvblas.so
    • NVBLAS_CONFIG_FILE
      作成したconfigファイルの場所を指定します。
      今回はここです。
      /etc/nvblas.conf

これでNVBLASの使用準備は完了です。

ベンチマーク実行

いよいよベンチマークを実行します。使用するベンチマークは、R-benchmark-25です。
まず、ベンチマークスクリプトをwgetしてきます。

wget http://r.research.att.com/benchmarks/R-benchmark-25.R

wgetしたファイルのあるフォルダで、ベンチマークを実行します。
最初はデフォルトのBLASを使っての測定なので、環境変数は設定しません。

cat R-benchmark-25.R | time R --slave

--- End of test ---の表記が出てきたら実行成功です。

次はNVBLASを使ってのベンチマーク実行です。

cat R-benchmark-25.R | LD_PRELOAD=/usr/local/cuda-9.0/lib64/libnvblas.so NVBLAS_CONFIG_FILE=/etc/nvblas.conf time R --slave

こちらも同じく、--- End of test ---の表記が出てきたら実行成功です。

結果

デフォルトBLAS

$ cat R-benchmark-25.R | time R --slave 
 要求されたパッケージ Matrix をロード中です 
 要求されたパッケージ SuppDists をロード中です 
 警告メッセージ: 
1:  remove("a", "b") で:   オブジェクト 'a' がありません 
2:  remove("a", "b") で:   オブジェクト 'b' がありません 

   R Benchmark 2.5
   ===============
Number of times each test is run__________________________:  3

   I. Matrix calculation
   ---------------------
Creation, transp., deformation of a 2500x2500 matrix (sec):  0.644 
2400x2400 normal distributed random matrix ^1000____ (sec):  0.514 
Sorting of 7,000,000 random values__________________ (sec):  0.682666666666666 
2800x2800 cross-product matrix (b = a' * a)_________ (sec):  16.576 
Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec):  5.81866666666667 
                      --------------------------------------------
                 Trimmed geom. mean (2 extremes eliminated):  1.36764279273898 

   II. Matrix functions
   --------------------
FFT over 2,400,000 random values____________________ (sec):  0.233333333333339 
Eigenvalues of a 640x640 random matrix______________ (sec):  1.74833333333334 
Determinant of a 2500x2500 random matrix____________ (sec):  2.71833333333333 
Cholesky decomposition of a 3000x3000 matrix________ (sec):  4.85133333333333 
Inverse of a 1600x1600 random matrix________________ (sec):  1.98166666666666 
                      --------------------------------------------
                Trimmed geom. mean (2 extremes eliminated):  2.11179869694154 

   III. Programmation
   ------------------
3,500,000 Fibonacci numbers calculation (vector calc)(sec):  0.477000000000004 
Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec):  0.199333333333328 
Grand common divisors of 400,000 pairs (recursion)__ (sec):  0.236333333333334 
Creation of a 500x500 Toeplitz matrix (loops)_______ (sec):  0.238 
Escoufier's method on a 45x45 matrix (mixed)________ (sec):  0.548999999999978 
                      --------------------------------------------
                Trimmed geom. mean (2 extremes eliminated):  0.29936896245831 


Total time for all 15 tests_________________________ (sec):  37.468 
Overall mean (sum of I, II and III trimmed means/3)_ (sec):  0.952673292595929 
                      --- End of test ---

170.66user 1.59system 2:52.37elapsed 99%CPU (0avgtext+0avgdata 433616maxresident)k
32480inputs+0outputs (63major+1004074minor)pagefaults 0swaps

NVBLAS

$ cat R-benchmark-25.R | LD_PRELOAD=/usr/local/cuda-9.0/lib64/libnvblas.so time R --slave
[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
 要求されたパッケージ Matrix をロード中です 
 要求されたパッケージ SuppDists をロード中です 
 警告メッセージ: 
1:  remove("a", "b") で:   オブジェクト 'a' がありません 
2:  remove("a", "b") で:   オブジェクト 'b' がありません 


   R Benchmark 2.5
   ===============
Number of times each test is run__________________________:  3

   I. Matrix calculation
   ---------------------
Creation, transp., deformation of a 2500x2500 matrix (sec):  0.64 
2400x2400 normal distributed random matrix ^1000____ (sec):  0.544666666666667 
Sorting of 7,000,000 random values__________________ (sec):  0.707999999999999 
2800x2800 cross-product matrix (b = a' * a)_________ (sec):  0.0803333333333332 
Linear regr. over a 3000x3000 matrix (c = a \ b')___ (sec):  0.642666666666666 
                      --------------------------------------------
                 Trimmed geom. mean (2 extremes eliminated):  0.607340415317063 

   II. Matrix functions
   --------------------
FFT over 2,400,000 random values____________________ (sec):  0.244333333333332 
Eigenvalues of a 640x640 random matrix______________ (sec):  0.698333333333334 
Determinant of a 2500x2500 random matrix____________ (sec):  1.05166666666667 
Cholesky decomposition of a 3000x3000 matrix________ (sec):  1.06566666666667 
Inverse of a 1600x1600 random matrix________________ (sec):  1.388 
                      --------------------------------------------
                Trimmed geom. mean (2 extremes eliminated):  0.921553927468368 

   III. Programmation
   ------------------
3,500,000 Fibonacci numbers calculation (vector calc)(sec):  0.505999999999998 
Creation of a 3000x3000 Hilbert matrix (matrix calc) (sec):  0.199666666666668 
Grand common divisors of 400,000 pairs (recursion)__ (sec):  0.234999999999999 
Creation of a 500x500 Toeplitz matrix (loops)_______ (sec):  0.241 
Escoufier's method on a 45x45 matrix (mixed)________ (sec):  0.555999999999997 
                      --------------------------------------------
                Trimmed geom. mean (2 extremes eliminated):  0.306016709184831 


Total time for all 15 tests_________________________ (sec):  8.80133333333333 
Overall mean (sum of I, II and III trimmed means/3)_ (sec):  0.555349040257246 
                      --- End of test ---

[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
[NVBLAS] NVBLAS_CONFIG_FILE environment variable is set to '/home/mori-yu/nvblas.conf'
38.43user 7.45system 0:46.10elapsed 99%CPU (0avgtext+0avgdata 850444maxresident)k
0inputs+7232outputs (0major+1566464minor)pagefaults 0swaps

全体の速度を比較したグラフは次のとおりです。

グラフ1

NVBLASを使用すると、約4.25倍の速度向上が確認できました。
一番差があった部分を比較したグラフを次に示します。

グラフ2

これは、行列同士の演算のテストです。
NVBLASの実装箇所であるBLAS Level 3ルーティンで、速度の違いを確認することができました。

まとめ

GPUを使用することで、「R」が高速化することがわかりました。
これからは、GPUのパワーをフル活用しながら、快適な「R」ライフを送りたいと思います。