Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

行列の積演算で openBLAS cuBLAS を体感する

More than 3 years have passed since last update.

Basic Linear Algebra Subprograms (BLAS) の 行列の積 演算が、C の for 文で率直に書いたルーチンに比べ、どれ程のものか体感してみる。

背景

  • 深層学習の実装を理解していくにあたり、行列の積演算を高速に行いたくなった。
  • BLASは 行列の積演算が速いとの話を目にするが、実際に使ってみたことはなかった。

→ 今回 BLAS の性能を体感してみる。

BLAS について

下記Webサイトを参考にしています。
Basic Linear Algebra Subprograms(Wikipedia)
BLASの簡単な使い方
CUDA Toolkit cuBLAS
インテル(R) 数値演算ライブラリ(MKL) リファレンス・マニュアル(PDF)

openBLAS

openBLAS はマルチスレッドにて CPUの全コアを用いた並列演算を行う。

cuBLAS

cuBLAS は NVIDIA のグラフィックカードのGPU上で並列演算を行う。

測定

測定内容

  • 行列の積演算 $C=αAB+βC$ $(A B C は行列、α βは スカラー値)$ を行う gemm() で測定を行う。

  • 一辺 num の 正方行列(下図)で、 num を増やしていった際の 所要時間で比較する。

行列の積.PNG

  • 各num で5回測定し平均値をプロット。

結果

グラフは下側が良く(所要時間が短い)、上側に行くほど悪い(所要時間が長い)。
C_vs_openBLS_vs_cuBLAS.png

(2017/5/5 追記)
グラフだけでは読み取り辛いので、num=2000の時の測定値を示します。

項目名 num=2000時の所要時間(ms) C Loop (col) を 1とした比
C Loop (col) 14902.36 1.00
C Loop (row) 17994.24 0.83
openBLAS (col) 288.02 51.74
openBLAS (row) 549.34 27.13
cublas 20.52 726.20
cublasXt (bd=num) 26.23 568.23
cublasXt (bd=num/2) 32.84 453.77

・openBLAS は C の for 文の率直版に比べ 25倍以上の差を確認しました。openBLAS すごい。予想以上でした。 C の for 文の率直版はシングルスレッドのため、openBLAS との差は 4倍~8倍(コア数~ハイパースレッド数)位かなと予想してました。25倍以上の差があるとは...。すごい。
・GPU の 並列演算 さらにすごい。gefoce1050ti な 15K円位のボードでも 率直C版に比べ 500倍以上の差を確認できました。次回 もっと詳しく見ていきます。

環境

項目 内容
CPU Intel(R) Core(TM) i7 CPU 920 @ 2.67GHz
M/B GIGABYTE EX58-DS4
メモリ 12GB
グラフィックカード 玄人志向 GF-GTX1050Ti-4GB/OC/SF
OS Ubuntu 16.04
グラフィックドライバ nvidia-375
CUDA 8.0.61-1
openBLAS 0.2.18-1ubuntu1
コンパイラ gcc Ubuntu 5.4.0-6ubuntu1~16.04.4

ルーチン

  • C loop (col) , C loop (row) のコンパイル時の最適化オプションは -O3

C の for loop での 率直な実装を示す。

C Loop (col)

#define MMCOL(X, di, i, j) ((X)[(j)*(di)+(i)])

    // C Loop (Col) 部分抜粋 
    // hst->A , hst->B , hst->C ともに num×num×sizeof(float) の メモリ領域

    gettimeofday(&st,NULL);
    for(int i=0;i<num;i++)
    {
        for(int j=0;j<num;j++)
        {
            float cc = 0.0;
            for(int k=0;k<num;k++)
            {
                cc += MMCOL(hst->A,num,i,k) + MMCOL(hst->B,num,k,j);
            }
            MMCOL(hst->C,num,i,j) += cc;
        }
    }

    gettimeofday(&et,NULL);

C Loop (row)

#define MMROW(X, dj, i, j) ((X)[(i)*(dj)+(j)])

    // C Loop (row) 部分抜粋 
    // hst->A , hst->B , hst->C ともに num×num×sizeof(float) の メモリ領域
    gettimeofday(&st,NULL);
    for(int i=0;i<num;i++)
    {
        for(int j=0;j<num;j++)
        {
            float cc = 0.0;
            for(int k=0;k<num;k++)
            {
                cc += MMROW(hst->A,num,i,k) + MMROW(hst->B,num,k,j);
            }
            MMROW(hst->C,num,i,j) += cc;
        }
    }
    gettimeofday(&et,NULL);

col , row 補足

  • C/C++言語では行優先(row Major) だが、Fortranでは 列優先 (Column Major)。
  • BLAS は 列優先 (Column Major) 。
  • openBLAS は row Major も利用可能。 
  • cuBLAS は Column Major のみ。

BLAS の 行列の積演算の 使い方

openBLSA では cblas_sgemm 関数を、cuBLASでは cublasSgemm 関数をよぶだけ。難しいだろうと身構えていたけども、今のところ躓きはなさそう。

次回

CUDA Toolkit cuBLAS のマニュアルを読み進めると、cuBLAS に拡張を加えた cuBLAS-XT が記載されてます。
次回は cuBLAS と cuBLAS-XT の違い、どちらを使うのが良いのか的な観点で調査します。

「cuBLAS と cuBLAS-XT の調査(その1)。行列の積演算にて」
「cuBLAS と cuBLAS-XT の調査(その2)。行列の積演算にて。転置の影響。」

t-tkd3a
機械学習 について実装できる位の理解を目指します。学ぶ過程の資料・成果を公開していきます。 また Linux での 開発環境・ツール類についても忘備録かねて記載していきます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away