2015/06/21(日)ubuntu 14.04でBLASを使う

ubuntu 14.04上でBLASをパッケージで入れて使ってみたのでメモを残しておきます。

BLASは、Basic Linear Algebra Subprogramsの略で、行列積などの基本的な行列計算のためのライブラリです。LAPACKなどの様々なプログラムから呼び出されます。行列計算は環境によって最適な書き方が違うので、行列計算の部分を差し替え可能なように分離しておきユーザが最適なBLASに差し替えて最高の性能を出す、ということを意図しています。

多くの環境で、デフォルトのBLASは単なるfor文で書かれたちっとも速くない「reference BLAS」と呼ばれるものになっています。自分の環境でも、reference BLASが入っていました。この場合例えばnumpyの行列計算は、全くCPU本来の性能を出せていません。

ubuntu 14.04では、atlasとopenblasという高速なBLASがパッケージで提供されています。今回は、それらをインストールしてnumpyの速度がどうなるか調べてみました。

インストールは次のように行いました。
sudo apt-get install libatlas-base-dev
sudo apt-get install libatlas-doc
sudo apt-get install libopenblas-base
sudo apt-get install libopenblas-dev
これで3種類のBLASがインストールされたことになりますが、これらは差し替えて使うことを意図しているのでshared libraryとして同一のファイル名になっています。Ubuntuでは、これらをsymbolic linkを張り直すことによって使い分ける仕組みがあります。
sudo update-alternatives --config libblas.so.3
と入力すると、
% sudo update-alternatives --config libblas.so.3
alternative libblas.so.3 (/usr/lib/libblas.so.3 を提供) には 3 個の選択肢があり>ます。

  選択肢    パス                                  優先度  状態
------------------------------------------------------------
* 0            /usr/lib/openblas-base/libblas.so.3      40        自動モード
  1            /usr/lib/atlas-base/atlas/libblas.so.3   35        手動モード
  2            /usr/lib/libblas/libblas.so.3            10        手動モード
  3            /usr/lib/openblas-base/libblas.so.3      40        手動モード

現在の選択 [*] を保持するには Enter、さもなければ選択肢の番号のキーを押してください:
のように表示され、どのBLASを使うか選択することができます。単にインストールした場合はUbuntuが定めた優先度に従って選ばれるようで、openblasが選択された状態でした。

これを切り替えてnumpyで5000x5000の逆行列を計算させてみて、速度がどうなるか計測してみました。環境は、core i7 3770T で、VMwareを使ってメモリを4G、CPUコアを4個与えた状態で行いました。

まずreference BLASで。
% python
>>> from numpy import *
>>> from time import *
>>> a=random.rand(5000,5000); t=time(); a=linalg.inv(a); time()-t
241.60200095176697
このように241秒かかりました。

ATLASに切り替えてみました。
% python
>>> from numpy import *
>>> from time import *
>>> a=random.rand(5000,5000); t=time(); a=linalg.inv(a); time()-t
32.59469819068909
32秒に高速化されました。しかし、topでCPUを見ると100%となっており、どうやら一つのコアしか使っていないようです。

最後にopenblasです。
% python
>>> from numpy import *
>>> from time import *
>>> a=random.rand(5000,5000); t=time(); a=linalg.inv(a); time()-t
6.014795780181885
6秒まで高速化されました。topのCPU表示は400%となり、4コア使って計算しているようです。

もともとテキサス大学の後藤先生という方が開発したgotoblas(ごとうブラス)という高速で有名なパッケージがあったのですが、後藤先生がIntelに移られて開発が中止してしまい、それを有志が引き継いだのがopenblasです。後藤先生は現在はIntelの商用BLASであるMath Kernel Libraryの開発をされているようです。

最後に、ATLASに関して少し注釈を述べておきます。
ATLASはAutomatically Tuned Linear Algebra Softwareの略で、ライブラリのmake時にそのCPUのコア数やキャッシュサイズなどを調査し、それに最適化したライブラリを生成する仕組みです。すなわち、本来バイナリパッケージで入れるには適さないもので、ATLASの真の性能を引き出すには計算を行うCPUでライブラリをmakeし直す必要があります。
また、ATLASはLAPACKの一部を高速化したものを含んでいて、ATLASをインストールするとATLAS版LAPACKがインストールされます。
% sudo update-alternatives --config liblapack.so.3
alternative liblapack.so.3 (/usr/lib/liblapack.so.3 を提供) には 2 個の選択肢があります。

  選択肢    パス                                    優先度  状態
------------------------------------------------------------
* 0            /usr/lib/lapack/liblapack.so.3             10        自動モード
  1            /usr/lib/atlas-base/atlas/liblapack.so.3   5         手動モード
  2            /usr/lib/lapack/liblapack.so.3             10        手動モード

現在の選択 [*] を保持するには Enter、さもなければ選択肢の番号のキーを押してください: 
しかし、このように優先度が低くなっており、デフォルトでは使われていません。これがUbuntuの(というかDebianの)開発チームの見解ということでしょうか。

2015/06/06(土)kv-0.4.21

kvライブラリを0.4.21にアップデートしました。

今回は、一応今までもひっそりと機能はあった、端点特異性を持つ関数の数値積分のコードを大幅に書き直し、機能も追加し、また詳細なwebドキュメントを書きました。端点特異性を持つ関数のうち、
  • 除去可能特異点を持つもの。例えば \int_0^1 \frac{\sin(x)}{x} dx
  • ベキ型特異点を持つもので、xpg(x)の形のもの。例えば \int_0^1 \sqrt{x}\cos(x)dx
  • ベキ型特異点を持つもので、f(x)pの形のもの。例えば \int_0^1 \sqrt{\sin(x)}dx
  • ベキ型特異点を持つもので、f(x)pg(x)の形のもの。例えば \int_0^1 \sqrt{\sin(x)}\cos(x)dx
  • log型特異点を持つもので、log(x)g(x)の形のもの。例えば \int_0^1 \frac{\log(x)}{x+1}dx
  • log型特異点を持つもので、log(f(x))の形のもの。例えば \int_0^1 \log(\sin(x))dx
  • log型特異点を持つもので、log(f(x))g(x)の形のもの。例えば \int_0^1 \log(\sin(x))\cos(x)dx
などを精度保証付きで計算できるようになりました。

その他、conj(共役複素数)を追加したり、全解探索における反復改良が稀にうまくいかなかったのを直したりしました。

最近少しずつユーザが増えてきて、最新のmacのclangで計算値が正しくないことがありそうとか、win7 32bit環境とVC++2012でddの表示がうまくいかないとか、報告を受けています。実機が用意できなかったりこちらでうまく再現しなかったりしてなかなか直せませんが、極力対応していきたいと考えていますので、こちらの環境(ubuntu 64bit)と異なる環境での動作報告、お待ちしております。

2015/04/16(木)kv-0.4.20

kvライブラリを0.4.20にアップデートしました。

今回は、主に端点に無限大を持つような区間に関するbug-fixです。区間演算ライブラリは、端点に無限大を持たせることによって半無限区間や全区間を取り扱えるように設計されています。区間演算の実装は、上端下端型と、中心半径型の2種類が考えられますが、本ライブラリでは半無限区間や全区間を扱えるという上端下端型のメリットを重視し、上端下端型を採用しています。

端点に無限大が入ると、無限大-無限大、無限大/無限大、無限大*0などでNaNが発生する危険性があり、これらを注意深く排除する必要があります。今回、乗算において思慮が浅かった部分が発見され、きちんと考えなおした上で修正しました。詳細なアルゴリズムは 端点に無限大を持つ区間演算まとめを見て下さい。無限大を扱わない場合は問題ありませんが、無限大を扱った計算において、0.4.19以前のライブラリの計算結果は精度保証されていなかった可能性があります。0.4.20へのアップデートをお勧めします。

また、sinh, coshに-無限大を入れた場合の不具合も修正しました。

2015/03/23(月)MSYS2を試してみる

日頃、研究のための作業のほとんどをubuntu上で行っています。研究者の多くはunix系の環境で仕事をすることを好んでおり、
  • macを使う。
  • windowsでvmware等の仮想環境を作り、その中でLinux等を使う。
  • windowsでcygwinを使う。
  • Linux等をマルチブートで使う。
などいろいろあると思います。本当に素のwindowsで仕事をする人は少ない気がします。拙kvライブラリも一応Visual Studioでも動くもののunix系で開発している関係上やはりunix系OSが使いやすい気がします。研究室の学生を見ると、windowsでcygwinを使っている人が大半のようです。自分はLinuxを入れることを勧めているのですが、やはり不慣れなOSで生活するのはつらいようで。

さて、windows環境のままunix系コマンドを使えるようにするソフトウェアとしてはcygwinが有名で長く使われてきていますが、最近MSYS2という同様のソフトウェアのいい評判をよく耳にします。そこで、試しにちょっと使ってみました。

元々、cygwinの亜種でmingw+msysというwindows nativeのexeを生成するソフトウェアがあるのですが、それの後継という位置づけで、
  • 比較的アップデートが早く、最新のソフトウェアが使える。
  • Arch Linuxで使われているpacmanというパッケージマネージャが使える。
という特徴があります。
上のページを見ながら、試しにインストールしてみました。インストール先はwindows7 64bit。
  • 64bit版のexe (msys2-x86_64-20150202.exe) をダウンロード。
  • 普通にインストーラを起動してインストール。デフォルトのc:\msys64に入れた。
  • スタートメニューからmsys2 shellを起動、終了、を2回繰り返す。
  • msys2 shell上で、最新にアップデートする。
    pacman -Sy(repositoryのデータを最新に)
    pacman --needed -S bash pacman pacman-mirrors msys2-runtime (再起動の必要のあるものを先にupdate)
    (msys2 shellを再起動)
    pacman -Su (残りをupdate)
    
pacmanパッケージマネージャの使い方は、以下の通り:
  • pacman -Ss 名前 で検索。
  • pacman -S 名前 でインストール。
  • pacman -R 名前 で削除。
さて、ややこしいことに、MSYS2はmsys2, mingw32, mingw64の3種類のbinaryを含んでおり、それぞれインストール場所も分けられています。msys2は、(cygwinがそんな感じであるように)msys-2.0.dllというmsys2独自のDLLがリンクされており、MSYS2環境下でしか動かないbinaryです。mingw32, mingw64はそれぞれwin32, win64のbinaryで、単独で動作します。gcc等のコンパイラも3種あって、msys2コンパイラで生成したexeはmsys2のDLLに依存しますが、mingw32/64のコンパイラで生成されたexeは単独で動作します。また、スタートメニューに登録された起動バッチファイルはmsys2_shell.bat, mingw32_shell.bat, mingw64_shell.batの3種類あって、msys2_shell.batから起動するとmsys2なbinaryにしかパスを通しません。mingw32/64.batで起動すると、mingwとmsys2の両方のbinaryにパスが通され、mingwの方が先に登録されているので優先されます。なるべく全てのbinaryをwindows nativeにしたかったが、どうしても無理なものだけmsys2依存で作成している、ということだと思います。

自分は、mingw64_shell.batを常用することにしました。

いくつかパッケージを入れて開発環境を整えてみました。前述したようにgccは3種類ありますが、公式Wikiの"Contributing to MSYS2"にあるように
pacman -S base-devel
pacman -S msys2-devel
pacman -S mingw-w64-i686-toolchain
pacman -S mingw-w64-x86_64-toolchain
で主だった開発に必要なものは大体入ります。更に、
pacman -S vim
pacman -S mingw-w64-x86_64-boost
pacman -S openssh
あたりを入れてみました。

この環境でkvライブラリはちゃんとコンパイル出来ました。mpfrを使ったものも、-lmpfr -lgmpを付けるだけでOK。

アンインストールも試してみましたが、コントロールパネルからで普通にきれいさっぱり消せるようです。

gccは4.9.2、boostは1.57.0であり、sshの最近のバグも修正されるなど、最新の環境が楽に使えるのはとてもいいですね。しばらく注目していようと思います。

2015/03/23(月)kv-0.4.19

kvライブラリを0.4.19にアップデートしました。

主な変更点は、
  • mpfrである程度以上仮数部の長い数を扱ったとき、e, ln2, piの定数の 精度が不十分なため区間幅が小さくならない問題を修正。
  • atanhの端点処理をちゃんとやるようにした。
  • ddとmpfrにceilとldexpを追加。
です。特に最初のが重要な修正です。

区間演算では、テンプレートを使って、interval<double>ならdoubleにふさわしい精度で、interval<dd>ならdouble-doubleにふさわしい精度で数学関数の計算を行う仕組みになっています。この仕組みで困るのが定数の計算で、定数は入力を持たないのでどの精度で計算すべきか判断できません。そこで、(numeric_limits<T>の使い勝手に倣って) constants<T>::pi(), constants<T>::e(), constants<T>::ln2()を用意し、Tの型によって計算精度を変える仕組みを採用しています。で、これらの実装は、例えばpiなら、
template <class T> struct constants< interval<T> > {
    static interval<T> pi() {
        static const interval<T> tmp(
            "3.1415926535897932384626433832795028841971693993751",
            "3.1415926535897932384626433832795028841971693993752"
        );
        return tmp;
    }
}
のように文字列で上端下端を与えそれを上下に丸めることによって得ていました。この定数は10進数50桁で円周率の上界下界になっています。doubleとddしか無ければこれだけ精度があれば十分だったのですが、mpfrで50桁以上の精度を指定した場合、(精度保証は出来ているものの)定数の区間幅が広すぎてまともな精度が出ない事態になっていました。ここの仕組みを変えて、きちんとその型なりの定数の計算方法を書くようにしました。
OK キャンセル 確認 その他