CLAPACKをVisual Studio 2010上で使う(32/64bit) (高速にLU分解がしたいので) 2012/05/18--
+ ATLASは,64bitでコンパイルするのが難しいらしい
- サーベイ
+ GOTOBLAS + LAPACKは,Core i7(Sandy Bridge CPU)ではうまくいかない(?)。解決できるんだろうけど時間がかかりそう
+ OpenBLAS + LAPACKは,MinGW+Cygwin環境でコンパイルできた.が、headerでVisual Sutio 2010にはもう入っていないcomplex.hを要求されたりしてちょっと使い難い.
+よってここのCLAPACKを利用する.
+ここからf2c.hとclapack.hをもらってくる
- *.h と *.libをダウンロード
+ここからコンパイル済みの*.libをもらってくる(自分でコンパイルした方が速そうだけど・・・上記のサーベイに丸1日かかってもう疲れた)
+Visual Studioのプロジェクトから見えるところに置いておく
- ヘッダをインクルードする
extern "C" { #include "f2c.h" #include "clapack.h" } #pragma comment(lib, "BLAS_nowrap.lib") #pragma comment(lib, "libf2c.lib") #pragma comment(lib, "clapack_nowrap.lib")
- コードを書く (LU分解)
void test() { integer N = 4; integer INFO ; long iPiv[4 ]; double a[16]={ 1.0, 5.0, 9.0, 4.0, 2.0, 11.0, 7.0, 14.0, 3.0, 10.0, 6.0, 15.0, 13.0, 2.0, 12.0, 1.0 }; //行列はColumn majourなのに注意 dgetrf_( &N, &N, a, &N, iPiv, &INFO ); for (int y= 0; y< 4; ++y ){ for (int x= 0; x< 4; ++x ) printf( "a[%d][%d]=%f ",y,x, a[ 4 * x + y] ); printf( "\n "); } for (int y= 0; y< 4; ++y ) printf( "iPiv[%d]=%d \n", y, iPiv[y]); }
- 結果
\\aにLU分解結果が入る
a[0][0]=9.000000 a[0][1]=7.000000 a[0][2]= 6.000000 a[0][3]=12.000000
a[1][0]=0.444444 a[1][1]=10.888889 a[1][2]=12.333333 a[1][3]=-4.333333
a[2][0]=0.555556 a[2][1]=0.653061 a[2][2]=-1.387755 a[2][3]=-1.836735
a[3][0]=0.111111 a[3][1]=0.112245 a[3][2]=-0.683824 a[3][3]=10.897059
//iPiv[i]には、i列目を分解する時に選択したピボット(行番号)が入る.
iPiv[0]=3
iPiv[1]=4
iPiv[2]=4
iPiv[3]=4
//これはつまり
1 2 3 4
↓(iPiv[0]=3)
3 2 1 4
↓(iPiv[1]=4)
3 4 1 2
↓(iPiv[2]=4)
3 4 2 1
という順序に列が並んでいるという事
- 結局
このサイトのコンパイル済みの.libで,3000×3000程度の密行列のLU分解に30秒強の時間がかかった.
ニューメリカルレシピに乗ってたコードをOpenMPを使ってちょっとチューニングした自分のコードの方が速くて残念.
OpenMPの製作者ががんばって開発を進めているようなので、そちらに期待しつつ、自分のLU分解を使うことにする.
- (追記)BundlerのソースコードにCLapack + BLASをVisual Studioのプロジェクト化したものがあった。これを利用したら速いバージョンのCLAPACKが得られるかも。