2012/03/10

OpenBLAS を使った Numpy/Scipy のビルド

Python, 作業ログ

はじめに

これまで BLAS には、高速な GotoBLAS を使ってきましたが、開発が終了していることから、移行先を検討していました。GotoBLAS の後継であり、開発が続いていることから、OpenBLAS を使うことにしました。研究室では Debian GNU/Linux を使用しており、作業当時のバージョンは squeeze です。


準備

必要なライブラリなどをインストール/ダウンロードします。まず、今回、独自にビルドしないライブラリなどを aptitude でインストールします。libatlas-base-dev が、後半で重要となります。

$ sudo aptitude install gfortran git swig
$ sudo aptitude install python python-numpy python-scipy python-nose
$ sudo aptitude install libsuitesparse-dev libatlas-base-dev

つぎに、適宜、ダウンロードしてきます。Numpy/Scipy は Source Forge からダウンロードします。

$ mkdir ~/tmp; cd ~/tmp
$ wget http://python.org/ftp/python/2.7.2/Python-2.7.2.tgz
$ wget http://pypi.python.org/packages/source/n/nose/nose-1.1.2.tar.gz
$ wget http://www.netlib.org/blas/blast-forum/cblas.tgz
$ wget http://www.netlib.org/lapack/lapack-3.4.0.tgz

OpenBLAS は github から取ってきます。

$ git clone git://github.com/xianyi/OpenBLAS

これで、必要なファイルがそろいました。


Numpy/Scipy 以外のビルド

今回 Python 2.7 のビルドは省略します。/usr/local にインストールされたものとします。また、事前に /usr/local/lib にパスを通しておきます。

$ sudo vim /etc/ld.so.conf.d/libc.conf
/usr/local/lib
$ sudo ldconfig

まずは、主役である OpenBLAS をビルドします。

$ cd ~/tmp/OpenBLAS/
$ vim Makefile.rule
...
# CBLAS/LAPACK は独自にビルドするので、以下のフラグを 1 にします。
# その他のオプションは環境にあわせて。
NO_CBLAS = 1
NO_LAPACK = 1
...
$ make
...
$ sudo make PREFIX=/usr/local install
...
$ sudo ldconfig

つぎに、CBLAS をビルドします。

$ cd ~/tmp
$ tar xzf cblas.tgz
$ cd CBLAS
$ vim Makefile.in
...
BLLIB = /usr/local/lib/libopenblas.a                                                                                                                  
CBLIB = ../lib/libcblas.a
...
LOADER = $(FC) -lpthread
...
# 最適化オプションで重要なのは -fPIC で、その他は好みに合わせて。
CFLAGS = -O2 -march=native -m64 -fomit-frame-pointer -fPIC -DADD_
FFLAGS = -O2 -march=native -m64 -fomit-frame-pointer -fPIC
$ make
...
$ cd lib
$ ar -x libcblas.a
$ gfortran -lopenblas -shared -o libcblas.so *.o
$ sudo cp libcblas.* /usr/local/lib/
$ sudo ldconfig

そして、LAPACK をビルドします。

$ cd ~/tmp
$ tar xzf lapack-3.4.0.tgz
$ cd lapack-3.4.0/
$ mv make.inc.example make.inc
$ vim make.inc
...
# 重要なのは -fPIC で、その他は好みに合わせて。
OPTS     = -O2 -march=native -m64 -fomit-frame-pointer -fPIC
...
NOOPT    = -O0 -fPIC
...
LOADOPTS = -lopenblas -lcblas
...
LAPACKLIB    = liblapack.3.4.0.a
$ make lapacklib
$ mkdir tmp; cd tmp
$ cp ../liblapack.3.4.0.a .
$ ar -x liblapack.3.4.0.a
$ gfortran -lopenblas -lcblas -shared -o liblapack.3.4.0.so *.o
$ sudo cp liblapack.3.4.0.* /usr/local/lib

最後に、必要なシンボリックリンクをはっていきます。

$ cd /usr/local/lib
$ sudo ln -sn liblapack.3.4.0.a liblapack.a
$ sudo ln -sn liblapack.3.4.0.so liblapack.so
$ sudo ln -sn /usr/lib/atlas-base/liblapack_atlas.a liblapack_atlas.a
$ sudo ln -sn /usr/lib/atlas-base/liblapack_atlas.so liblapack_atlas.so

ここで重要なのは、liblapack_atlas にリンクをはっているところです。liblapack_atlas なしに、Scipy をビルドすると、テストで以下のエラーが出てしまいます。

clapack.so: undefined symbol: clapack_sgesv

sgesv が関わる scipy.linalg は固有値分解などの関数を含むので、見逃すことはできません。以上で準備完了です。


Numpy/Scipy のビルド

まず Numpy をビルドします。

$ cd ~/tmp
$ tar xzf numpy-1.6.1.tgz
$ cd numpy-1.6.1/
$ vim site.cfg
[atlas]
atlas_libs = lapack_atlas,openblas,cblas
$ python setup.py config
...
$ python setup.py build
...
$ sudo python setup.py install
...

そして Scipy をビルドします。

$ cd ~/tmp
$ tar xzf scipy-0.10.1.tgz
$ cd scipy-0.10.1
$ python setup.py config
...
$ python setup.py build
...
$ sudo python setup.py install
...

Numpy/Scipy のテスト

テストのために nose をインストールします。

$ cd ~/tmp
$ tar xzf nose-1.1.2.tar.gz 
$ cd nose-1.1.2/
$ python setup.py build
$ sudo python setup.py install

テストを実行して OK がでれば問題ありません(のはずです)。

$ python -c "import numpy; numpy.test(verbose=2)"
...
OK (KNOWNFAIL=3, SKIP=5)
$ python -c "import scipy; scipy.test(verbose=2)"
...
OK (KNOWNFAIL=13, SKIP=30)

おわりに

OpenBLAS は Ubuntu などにはパッケージがあるようなので、今後 Debian にもパッケージが追加されることを期待したいところです。

このエントリーをはてなブックマークに追加