Reference BLAS → OpenBLAS

 

Screenshot from 2016-04-09 17-24-55

Lapackをインストールする際に勝手に入るBLASは,Netlibのリファレンス実装で,こいつは速度が遅い.そのためLapack が依存している BLASを,Reference BLAS から OpenBLASに切り替えたときのメモ.(OSは,fedora 23)

そこでまず,LapackがどこからBLASをひっぱてきているのか調べる.

最初に適当にLapackを使ってコンパイルし,実行ファイルが何に依存しているか以下の通り調べる.

$ gfortran -llapack test.f
$ ldd a.out
linux-vdso.so.1 (0x00007ffdc4659000)
liblapack.so.3 => /lib64/liblapack.so.3 (0x00007f6e0ea6d000)
libgfortran.so.3 => /lib64/libgfortran.so.3 (0x00007f6e0e741000)
libm.so.6 => /lib64/libm.so.6 (0x00007f6e0e43e000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f6e0e227000)
libquadmath.so.0 => /lib64/libquadmath.so.0 (0x00007f6e0dfe8000)
libc.so.6 => /lib64/libc.so.6 (0x00007f6e0dc26000)
libblas.so.3 => /lib64/libblas.so.3 (0x00007f6e0b905000)
/lib64/ld-linux-x86-64.so.2 (0x000055bfaf841000)

以上にて,/lib64/libblas.so.3 からBLASをひっぱてきてることがわかった.
次に/lib64/libblas.so.3はシンボリックリンクなので,どこを参照しているか調べる.

$file /lib64/libblas.so.3
/lib64/libblas.so.3: symbolic link to libblas.so.3.5.0

以上より, Lapack → libblas.so.3 → libblas.so.3.5.0 のようにReference BLASを参照していることがわかった.

そこで,Lapack → libblas.so.3 → OpenBLAS のように参照するようにしてあげれば,OpenBLASに切り替えることができる.

まずOpenBLASをインストールする.

#dnf install openblas

次にalternativesコマンドで,OpenBLASに切り替える.使用するOSによっては,すでに登録されている場合があるが(#update-alternatives –list で確認できる),fedoraは登録されていないので,登録作業から始める必要がある.登録の際は,以下のコマンドにて行う.

#alternatives –install リンク名 総称名 選択候補 優先度

alternativesコマンドの詳細は,ココ(https://vinelinux.org/)で確認のこと.

以下コマンドにて,登録を行った.

#alternatives –install /lib64/libblas.so.3 libblas.so.3 /lib64/libblas.so.3.5.0 10

#alternatives –install /lib64/libblas.so.3 libblas.so.3 /lib64/libopenblas.so 20

次に,以下コマンドで設定の状態を確認する.

#update-alternatives –config libblas.so.3

There are 2 programs which provide ‘libblas.so.3’.
Selection Command
———————————————–
1 /lib64/libblas.so.3.5.0
*+ 2 /lib64/libopenblas.so
Enter to keep the current selection[+], or type selection number:

/lib64/libopenblas.so のところに[+]がついていれば,libblas.so.3 は,libblas.so.3.5.0 から libopenblas.soを参照するようになる.( /lib64/libblas.so.3.5.0 のところに[+]がつくように設定を変更すれば,以前と同じReference BLAS を使用することになる.)

最後にOpenBLASに切り替えた効果を確認する.確認用のプログラム(lapack_test.f)を書いてみた.中身は連立一次方程式 Ax=B(A:1000×1000の密行列)をdgesvを使って解くプログラム.

$gfortran -llapack lapack_test.f

Reference BLASの場合

$ ./a.out
DGESV works fine
0.55200000000000005 ←実行時間

OpenBLASの場合

$ ./a.out
DGESV works fine
0.14699999999999999 ←実行時間

確認の結果,上記の例では4倍ほど高速化できていることがわかる.

なお,SuperLUは標準でATLASを使用しており,ATLASとOpenBLASを切り替えて比較してみたが,計算時間はほとんど同じだった.

参考

https://vinelinux.org/docs/vine6/cui-guide/update-alternatives.html
http://www.nag-j.co.jp/fortran/tips/tips_PortableWayToTime.html

intel fortran + PARDISO → gfortran + SuperLU

Screenshot from 2015-11-30 00-49-08

疎行列連立一次方程式(Ax=B)の計算には,MKLに収録されている”PARDISO”を使っていたが,環境をintel fortran + MKL からgfortran + Lapack95 に移行したのに合わせて,”SuperLU”に移行したのでメモ.(OSは,fedora 22)

まず,SuperLUをインストール.

#dnf install SuperLU

次に,正常にインストールできていることを確認する.

サンプルコードを入手するため,まずSuperLU本体をココ(http://crd-legacy.lbl.gov/~xiaoye/SuperLU/)からダウンロードする.

次に/SuperLU_*/EXAMPLE (*はSuperLUのver.)の中に入っている,”superlu.c”を以下コマンドでコンパイル/実行する.(ここで,superlu.cの冒頭を”int main(int argc, char *argv[]”と書き換えないとコンパイルは通らないので注意.)

$gcc -lsuperlu -I/usr/include/SuperLU superlu.c

$./a.out

正常なら上記コンパイル及び実行ができるはず.

 

C言語からはSuperLUを直接利用できる.しかし,FortranからSuperLUを使用する場合,ラッパーを書いてあげる必要がある.(/SuperLU_*/FORTRAN 内のファイルを参考にすると良い)

そこで,ラッパーとなるCプログラム(dgssv.c)と,SuperLUを呼び出すFortranプログラム(test.f90)を書いてみた.

なお,test.f90では例として,

A =
1 2 3 0
0 0 0 1
2 0 0 2
0 1 0 1

B =
2
3
1
2

の疎行列連立方程式を解くこととしている.

SuperLUでは,CRS形式またはCCS形式(疎行列の格納方法はココを参照)等の疎行列格納方法を使用できる.今回はCRS形式を使用することとしている.

もし,CCSなど別の形式を使用したい場合は,dgssv.cの中身を書き換える必要がある.(superlu.cはCCS形式で計算しているので,比較すればどのあたりを変えればいいかわかるはず.)

また,FortranからC言語で書いたプログラムを呼ぶ場合は,配列の処理等々注意する必要がある.(ココを参考)

dgssv.c と test.f90をコンパイルするには,以下コマンドを叩く.

$gcc -c -I/usr/include/SuperLU dgssv.c

$gfortran -lsuperlu -lblas dgssv.o test.f90

うまくコンパイルできていれば,”a.out”ができているので,実行すれば以下が表示されるはず.

$./a.out

Success dgssv
-2.5000000000000000
-1.0000000000000000
2.1666666666666665
3.0000000000000000

 

参考だがSuperLUでは,様々な設定ができる.具体的にはdgssv.cの中の以下で設定している.

set_default_options(&options);
options.ColPerm = NATURAL;

上記では,まずすべての設定をデフォルトとし,そのうち”ColPerm”の内容だけ,”NATURAL”に変更している.

なお設定項目の詳細は,/SuperLU_*/DOC 内のSuperLUのマニュアルに記載してあるので参照のこと.

 

参考

http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html

http://netlib.org/linalg/html_templates/node91.html

intel fortran + MKL → gfortran + Lapack95

Screenshot from 2015-09-07 01-50-18

intel fortran + MKL から,gfortran + Lapack95 に移行したのでメモ.(OSは,fedora 22)

まず,gfortran と LAPACK をインストール.(BLASも依存関係にあるので,同時に入るはず)

#dnf install gcc-gfortran lapack lapack-devel

問題なくインストールできていれば,DGESVのサンプルコード(software.intel.com)を “test.f” に保存して

$gfortran test.f -lblas -llapack

でコンパイルできるはず.

 

次に,LAPACK95のソースをNetlib(http://www.netlib.org/lapack95/)からダウンロードし,”lapack95.tgz”を適当なところに解凍する.

“LAPACK95″というディレクトリができているはずなので,その中で以下を実行.

$ mv SRC/makefile SRC/Makefile
$ mkdir lapack95_modules

“make.inc” を以下の通り編集.

FC = gfortran
FC1 = gfortran

OPTS0 = -O3
MODLIB = -I./../lapack95_modules
OPTS1 = -c $(OPTS0)
OPTS3 = $(OPTS1) $(MODLIB)
OPTL = -o
OPTLIB =

LAPACK_PATH = -L/usr/lib64

LAPACK95 = -llpack95
LAPACK77 = -llapack
TMG77 = -ltmglib
BLAS = -lblas

最後に,以下を実行してLAPCK95をコンパイル.

$ cd SRC
$ make single_double_complex_dcomplex

これで”lapack95.a” と “lapack95_modules” 内に,モジュール中間ファイルが作成されているはず.

後は,適当なディレクトリ(例えば”/usr/lib64/lapack95″, “/usr/include/lapack95″)を作ってその中にlapack95.aとlapack95_modulesをコピー.

# mkdir /usr/lib64/lapack95
# mkdir /usr/include/lapack95

# cp lapack95.a /usr/lib64/lapack95/liblapack95.a
# cp lapack95_modules/*.mod /usr/include/lapack95

そんでもって “liblapack95.a”に対し,pathの通っている”/usr/lib64″へシンボリックリンクを貼る.

# ln -s /usr/lib64/lapack95/liblapack95.a /usr/lib64/liblapack95.a

これでLAPACK95を使う準備完了のはず.ココ(http://nagappi.hatenablog.com)のサンプルコードを,”inv.f90″に保存して以下が実行できていればOKな「はず」.

$ gfortran inv.f90 -llapack95 -llapack -lblas -I/usr/include/lapack95/

参考

http://www.rcs.arch.t.u-tokyo.ac.jp/kusuhara/tips/linux/fortran.html

http://nagappi.hatenablog.com/entry/20121227/1356582470