OpenBLAS, ATLAS, BLASとの性能比較|行列積高速化#28
そこそこ高速な実装ができたので、他のBLASライブラリが持つDGEMMと性能比較を行ってみましょう。
比較を行うライブラリとしては、下記を使用しました。
1、BLAS(NetLibの参照実装)
2、ATLAS
3、OpenBLAS
これらのライブラリについては、下記でも紹介しています。
GCCの準備
評価環境として使用しているMacBookでは、OpenBLASはbrewでインストール可能でしたが、BLASとATLASは独自にコンパイルする必要がありました。
コンパイルにあたり、デフォルトのコンパイラclangだと色々な問題が発生したため、brewを使用してあらかじめインストールしておいたgcc10とgfortranをコンパイラとして使用しました。
$brew install gcc gfortran
OpenBLASのインストール
OpenBLASは下記のコマンドでインストールできました。
$ brew install openblas
OpenBLASは、/usr/local/Cellar/openblas/0.3.10_1/libにインストールされているため、MakefileのLDFLAGSにパスを追加する必要があります。
LDFLAGS=-L./lib/ -L/usr/local/Cellar/openblas/0.3.10_1/lib/
CBLASLIBS= -lcblas -lopenblas
ATLASのインストール
ATLASは、まずsourceforgeからソースコードatlas3.10.3.tar.bz2をダウンロードします。
次のコマンドで解凍後、作成されたATLASディレクトリに移動します。
$ tar jxvf atlas3.10.3.tar.bz2
$ cd ATLAS/
次に、評価環境専用のディレクトリを任意の名前で作る必要があります。ここでは、ディレクトリ名をATLAS_MacOSXとしました。その後、作成したディレクトリに移動します。
$ mkdir ATLAS_MacOSX
$ cd ATLAS_MacOSX
ATLASでは、configureでCPUを推測してくれるのですが、評価環境のMacBookの場合はエラーが出て、推測に失敗してしまいました。結局、必要なパラメータをコマンドラインオプションとして指定する必要がありました。
一つ上のディレクトリにあるconfigureスクリプトを実行したあと、makeを実行します。コマンドは、下記の通りです。
$ ../configure --prefix=./install -O OSX -A UNKNOWNx86 -V 16 -b 64 -t 2 -m 2900
$ make
インストール先を決める--prefixには、一旦その場に作成されるように./installを指定しました。-OはOS名、-AはCPU名、-Vは使用する命令セットのビットフラグ、-bはアドレスのビット数(64bit)、-tはスレッド数、-mはMHz単位の動作周波数(2900MHz)です。
OS名やCPU名、及び命令セットは、途中で作成されるxprint_enumを実行すると確認できます。CPU名には、適切なものがなかったのでUNKNOWNx86を選びました。命令セットは、AVXMAC=16を選んでいます。
makeコマンドで、自動チューニングが始まりますが、これには時間がかかります。経験上では3~4時間かかることが多いですが、今回は62時間(約2.5日)かかりました。。。
自動チューニングが完了したら、完成したライブラリを適当なディレクトリに移動させます。今回は、OpenBLASと同じく、/usr/local/Cellarの配下に移動しました。
$ mv ./install /usr/local/Cellar/atlas
ただし、ATLASが作成したライブラリlibcblas.aは、BLASが作成するlibcblas.aと名前が重複するので、ATLASが作成したものをlibcblas_atlas.aに変更しました。
最後に、atlasをリンクする場合には、Makefileで次のように指定します。
LDFLAGS=-L./lib/ -L/usr/local/Cellar/atlas/lib/
CBLASLIBS= -lcblas_atlas -latlas
BLASのインストール
NetLib.orgの下記のサイトから、blas-3.8.0.tgz、cblas.tgz、及びcblas.hをダウンロードします。
拡張子は.tgzですが、実施にはgzip圧縮はされていないので、次のようなtarコマンドで解凍します。
$ tar xvf blas-3.8.0.tgz
$ tar xvf cblas.tgz
解凍すると、BLAS-3.8.0/およびCBLAS/ディレクトリが作成されます。
ビルドの前に、環境に合わせて設定ファイルBLAS-3.8.0/make.incおよびCBLAS/Makefile.inを修正する必要があります。今回は、次のように設定しました。
$ cat BLAS-3.8.0/make.inc
####################################################################
# BLAS make include file. #
# March 2007 #
####################################################################
#
SHELL = /bin/sh
#
# The machine (platform) identifier to append to the library names
#
PLAT = _MACOSX
#
# Modify the FORTRAN and OPTS definitions to refer to the
# compiler and desired compiler options for your machine. NOOPT
# refers to the compiler options desired when NO OPTIMIZATION is
# selected. Define LOADER and LOADOPTS to refer to the loader and
# desired load options for your machine.
#
FORTRAN = gfortran
OPTS = -O3 -mavx2
DRVOPTS = $(OPTS)
NOOPT =
LOADER = gfortran
LOADOPTS =
#
# The archiver and the flag(s) to use when building archive (library)
# If you system has no ranlib, set RANLIB = echo.
#
ARCH = ar
ARCHFLAGS= cr
RANLIB = ranlib
#
# The location and name of the Reference BLAS library.
#
BLASLIB = ../../lib/libblas.a
$ cat CBLAS/Makefile.in
#
# Makefile.LINUX
#
#
# If you compile, change the name to Makefile.in.
#
#
#-----------------------------------------------------------------------------
# Shell
#-----------------------------------------------------------------------------
SHELL = /bin/sh
#-----------------------------------------------------------------------------
# Platform
#-----------------------------------------------------------------------------
PLAT = MACOSX
#-----------------------------------------------------------------------------
# Libraries and includs
#-----------------------------------------------------------------------------
BLLIB = ../../../lib/libblas.a
CBLIB = ../../../lib/libcblas.a
#-----------------------------------------------------------------------------
# Compilers
#-----------------------------------------------------------------------------
CC = gcc
FC = gfortran
LOADER = $(FC)
#-----------------------------------------------------------------------------
# Flags for Compilers
#-----------------------------------------------------------------------------
CFLAGS = -O3 -mavx2 -DADD_
FFLAGS = -O3 -mavx2
#-----------------------------------------------------------------------------
# Archive programs and flags
#-----------------------------------------------------------------------------
ARCH = ar
ARCHFLAGS = r
RANLIB = echo
以上の設定ができたら、下記のコマンドを使ってビルドします。
$ cd BLAS-3.8.0
$ make
$ cd ../CBLAS
$ make alllib
性能比較
BLASライブラリを差し替えてDGEMMの実行性能を測定したところ、次のようになりました。
縦軸は、理論ピーク性能比率(=FLOPS/PEAK FLOPS)を表しています。横軸は、正方行列の片方のサイズを表しています。つまり、横軸1000の場合は1000x1000の大きさの行列積を計算しています。
myblas(青線)が、今回作成した行列積計算プログラムです。行列サイズが大きくなると、およそ90~93%の性能が出ています。しかし、openblas(オレンジ線)は、だいたい97~101%の性能が出ています(100%を超えるのは、演算数カウントが多すぎるのかもしれません)。従って、およそ7%前後のopenblasよりも劣っていることが分かります。ただし、ほぼ同じ曲線を描いているので、高速化チューニングとして同じような実装を行っていると推測されます。
atlas(黄色線)は、自動チューニングに失敗しているのでしょう。これまでの経験上では、80%から90%の性能は出るはずです。これは、指定したオプションが適切ではなかった可能性が高いです。(でも、自動チューニングに2.5日かかったので、もう一度ビルドする気になれません・・・)
blas(灰色線)は、小さい行列では20%を超える性能が出ています。-mavx2オプションなしだと10%前後の性能だったため、これはAVX命令の効果だと考えられまう。しかし、行列サイズが大きくなると、10%前後に性能が落ちて来ています。これまでの経験上でも、blasは10%程度の性能でした。
まとめ
同じような曲線を描くものの、OpenBLASの方が7%前後高速でした。
さすがですね。
高速化のポイントが、もう1つか2つほどあるのかもしれません。
次の記事
ソースコード