BLASはBasic Linear Algebra Subprogramsの略で線型代数の基本的な演算を行なうためのライブラリ群です. この中には行列の積や和,行列とベクタの積などの行列計算が含まれます. Fortranで開発されており,数値計算用ライブラリとして精度,安定性に定評があります. ここではBLASをC言語から利用するためのインターフェース,CBLASについて説明します. このマニュアルで扱うCBLASはATLASによって提供されるC言語インターフェースを想定していますが, intelのMKL (Math Kernal Library)やGSL (GNU Scientific Library) のCBLASもほぼ同じ方法で使うことができると思われます. これはCBLASにはインターフェース規約というものが存在し, 関数の仕様が決められているためです.
ATLASはAutomatically Tuned Linear Algebra Softwareの略でコンパイル時に自動的にCPUを始めとする, 計算機の実行条件に合わせて最適化を行なったBLASの一種です. SSE等のCPU特殊命令についても使用/不使用が自動的に設定されます. このため,一般にBLASよりも高速であり,通常の場合はこちらを使うことが推奨されます.
上述のようにATLASはBLASの上位互換と考えることができます. 加えて,ATLASにはLAPACKの一部のルーチンも同時に最適化を行ないます. これらの最適化ルーチンについてはライブラリのリンクのところで詳述します.
本研究室の標準インストールに従っていれば,BLAS,ATLASはインストールされているはずです, 何らかの理由でインストールされていない場合は管理者に相談してください. 一般の方はLAPACK (FAQ)を参照してください. ここで,Visual Studioと心中する覚悟のある方は, 番外編 (1)を参照してください.
利用の前に注意しなければならないことについて解説します.
二次元配列をメモリ上に格納する際のルールがFortranとC言語とでは異なります. 以下の行列(二次元配列)を例にとり説明します. Fortranは列形式でこれを格納します. つまりメモリアドレスの小さい順に, a,d,g,b,e,h,c,f,iとなります. C言語は行形式, a,b,c,d,e,f,g,h,iとなります. BLASのC言語インターフェースであるCBLASルーチンは引数によって行形式も列形式も扱えるようになっていますが, LAPACKとの連携を考えると列形式を利用すべきでしょう. 行列の形式の指定は列形式がCblasColMajor,行形式がCblasRowMajorです.
本マニュアルはlda,ldb等,LD?なる変数を「行列の行数」として言及していますが, これは本来は「Leading Dimension of ?」,「配列?の第一次元」であり, メモリ空間上で連続的に配置される要素の要素数を意味します. 二次元配列の格納形式に列形式(CblasColMajor)を採用した場合, メモリ空間上に連続的に配置されるのは列要素ですから,その要素数たるLD?は「行列の行数」となります. しかしながら,C言語の標準の格納形式である行形式(CblasRowMajor)を採用した場合, メモリ空間上に連続的に配置されるのは行要素ですから, LD?は「行列の列数」となります. したがって,格納形式を変更する場合はLD?を適宜読み替えてください.
また,Fortranの二次元配列の要素は必ず連続領域でなければなりませんが,
C言語は二次元配列は一次元配列へのポインタへの配列を意味しますから,
自動変数として確保した場合を除けば,要素の実体の領域が連続であるとは限りません.
したがって,二次元配列A[i][j]
などとして作った行列を,
ポインタとしてCBLASの関数に与える場合は,
格納形式だけでなく必ず実体が連続的に配置されていることもまた確認してください.
Fortranはサブルーチンのコールの際に値渡しを行なうことができません. 引数は全てポインタとなります. しかしながら,CBLASルーチンはこのことが考慮されており,値で引数を渡せるようになっています.
変数の型と精度は以下の表のようになります.複素数は正味ポインタとなる,と考えてください. 各種ルーチンの?の部分に入ります.
変数の型 | 略号 | 備考 |
---|---|---|
単精度実数 | s | float |
倍精度実数 | d | double |
単精度複素数 | c | *float |
倍精度複素数 | z | *double |
このほかに,関数の場合は引数と戻り値の型が異なる場合があります. ds等と表記する場合がそれです,これは,単精度実数を引数として倍精度実数を返すことを意味します.
CBLASは特殊な型の行列に対してより高速な演算を行なうルーチンを提供します. 以下の表にそうした行列の型を挙げます.
名称 | 略号 | 例 | 説明 |
---|---|---|---|
一般行列(General Matrix) | ge | 要素の配置に制約のない一般的な行列です. | |
一般帯行列(General Band Matrix) | gb | 非零の要素が主対角線上とそれに平行な帯の中に存在する行列です. 応用上良く現れます.左の例は3重対角行列です. | |
対称行列(Symmetric Matrix) | sy | 転置行列がもとの行列と等しくなる行列です.主に実行列のことを指します. やはり,応用上良く現れます. | |
対称帯行列(Symmetric Band Matrix) | sb | 転置行列がもとの行列と等しくなる帯行列です. | |
エルミート行列(Hermitian Matrix) | he | 転置共役行列がもとの行列と等しくなる行列です.主に複素行列ですが対角要素は実数です. 応用上良く現れます. | |
エルミート帯行列(Hermitian Band Matrix) | hb | 転置共役行列がもとの行列と等しくなる帯行列です. | |
三角行列(Triangular Matrix) | tr | 非零の要素が主対角線上の上のみ(下のみ)に存在する行列です. 左の例は上三角行列です. | |
三角帯行列(Triangular Band Matrix) | tb | 非零の要素が主対角線上とその上の(下の)平行な帯の中に存在する行列です. 左の例は上三角帯行列です. |
CBLASが提供するルーチンの内,幾つかのものは行列に対する事前の演算を指定する必要があります. ここで用いる定数はcblas.h内で定義されています.
BLASには演算の種類によって三種類の分類が存在します. 大まかに次のように分類されています.
ベクタ─ベクタ演算ルーチンを提供します.
ベクタ─行列演算ルーチンを提供します.
行列─行列演算ルーチンを提供します.
既に述べた通り,Level 1 BLASはベクタ─ベクタ演算ルーチンを提供します. BLASは高速化のために演算に2オペランド方式を採用しています. このため,演算に供されるベクタの内,必ず一方の値が失われることを覚えておいてください.
ルーチンの説明は提供される精度を挙げたあと, 最も良く利用すると思われる精度のルーチンについて引数と戻り値を解説します.
まずLevel 1 BLASの全ルーチンを表にします.
ルーチン名 | 精度と型 | 演算の内容 |
---|---|---|
cblas_?rotg | s, d, c, z | Givens rotation of points (routines) |
cblas_?rotm | s, d | Modified plane rotation of points |
cblas_?rotmg | s, d | Givens modified plane rotation of points |
cblas_?rot | s, d, cs, zd | Plane rotation of points (routines) |
cblas_?swap | s, d, c, z | あるベクタ同士を交換します. |
cblas_?scal | s, d, c, z, cs, zd | あるベクタをスカラー倍します. |
cblas_?copy | s, d, c, z | あるベクタをコピーします. |
cblas_?axpy | s, d, c, z | ベクタ同士を加算します. |
cblas_?dot | s, d | ベクタ同士のドット積を計算します. |
cblas_?dotu_sub | c, z | 複素ベクタ同士のドット積を計算します(転置). |
cblas_?dotc_sub | c, z | 複素ベクタ同士のドット積を計算します(共役転置). |
cblas_sdsdot | sds | Dot product with extended precision (functions) |
cblas_?nrm2 | s, d, sc, dz | ベクタの二次ノルムを計算します. |
cblas_?asum | s, d, sc, dz | ベクタの絶対値の和を計算します. |
cblas_i?amax | s, d, c, z | ベクタの要素の中で絶対値の最も大きなもののインデックスを計算します. |
あるベクタ同士を交換します.
cblas_sswap(),cblas_dswap(),cblas_cswap(),cblas_zswap()
void cblas_dswap(const int N, const double *X, const int incX, double *Y, const int incY);
戻り値はありません.
あるベクタをスカラー倍します.
cblas_sscal(),cblas_dscal(),cblas_cscal(),cblas_zscal(),cblas_csscal(),cblas_zdscal()
void cblas_dscal(const int N, const double alpha, double *X, const int incX);
戻り値はありません.
あるベクタをコピーします.
cblas_scopy(),cblas_dcopy(),cblas_ccopy(),cblas_zcopy()
void cblas_dcopy(const int N, const double *X, const int incX, double *Y, const int incY);
戻り値はありません.
ベクタ同士を加算します.
cblas_saxpy(),cblas_daxpy(),cblas_caxpy(),cblas_zaxpy()
void cblas_daxpy(const int N, const double alpha, const double *X, const int incX, double *Y, const int incY);
戻り値はありません.
ベクタ同士のドット積を計算します.
cblas_sdot(),cblas_ddot(),cblas_dsdot()
double cblas_ddot(const int N, const double *X, const int incX, const double *Y, const int incY);
演算結果のドット積が返されます.
複素ベクタ同士のドット積を計算します.片方の複素ベクタの転置が演算に供されます. 演算結果が複素数であることに注意してください.
cblas_cdotu_sub(),cblas_zdotu_sub()
void cblas_zdotu_sub(const int N, const void *X, const int incX, const void *Y, const int incY, void *dotu);
戻り値はありません.
複素ベクタ同士のドット積を計算します.片方の複素ベクタの共役転置が演算に供されます. 演算結果が複素数であることに注意してください.
cblas_cdotc_sub(),cblas_zdotc_sub()
void cblas_zdotc_sub(const int N, const void *X, const int incX, const void *Y, const int incY, void *dotu);
戻り値はありません.
ベクタの二次ノルムを計算します.
cblas_snrm2(),cblas_dnrm2(),cblas_scnrm2(),cblas_dznrm2()
double cblas_dnrm2(const int N, const double *X, const int incX);
演算結果の二次ノルムが返されます.
ベクタの絶対値の和を計算します.
cblas_sasum(),cblas_dasum(),cblas_scasum(),cblas_dzasum()
double cblas_dasum(const int N, const double *X, const int incX);
演算結果の絶対値の和が返されます.
ベクタの要素の中で絶対値の最も大きなもののインデックスを計算します.
cblas_isamax(),cblas_idamax(),cblas_icamax(),cblas_izamax()
CBLAS_INDEX cblas_idamax(const int N, const double *X, const int incX);
ベクタの要素の中で絶対値の最も大きなもののインデックスが返されます.
Level 2 BLASはベクタ─行列演算ルーチンを提供します. Level 1 BLAS同様に左辺値の計算対象が右辺にも存在します. このため,演算に供されるベクタまたは行列の内,必ず一つの値が失われることを覚えておいてください.
本節で初めて行列が登場します.CBLASは行形式,列形式双方の行列を扱うことができますが, LAPACKとの併用を考えた場合,列形式での利用をお勧めします. また,演算に供する行列が既述の特殊な型に該当する場合,専用のルーチンを利用した方が 速度/精度の面で有利になります.
特殊な型の行列,対称(エルミート)行列(sy,he)と三角行列(tr) はCBLAS_UPLOで指定した三角部分以外は不定値(正確には更新されない)となりますので特に注意が必要です. 必ずサンプルコードに目を通してください.
ルーチンの説明は提供される精度を挙げたあと, 最も良く利用すると思われる精度のルーチンについて引数と戻り値を解説します.
Level 2 BLASの全ルーチンを表にします.
ルーチン名 | 精度と型 | 演算の内容 |
---|---|---|
cblas_?gbmv | s, d, c, z | Matrix-vector product using a general band matrix |
cblas_?gemv | s, d, c, z | ベクタと一般行列の積を計算します. |
cblas_?ger | s, d | 列ベクタと行ベクタの積を計算します. |
cblas_?gerc | c, z | Rank-1 update of a conjugated general matrix |
cblas_?geru | c, z | Rank-1 update of a general matrix, unconjugated |
cblas_?hbmv | c, z | Matrix-vector product using a Hermitian band matrix |
cblas_?hemv | c, z | Matrix-vector product using a Hermitian matrix |
cblas_?her | c, z | Rank-1 update of a Hermitian matrix |
cblas_?her2 | c, z | Rank-2 update of a Hermitian matrix |
cblas_?hpmv | c, z | Matrix-vector product using a Hermitian packed matrix |
cblas_?hpr | c, z | Rank-1 update of a Hermitian packed matrix |
cblas_?hpr2 | c, z | Rank-2 update of a Hermitian packed matrix |
cblas_?sbmv | s, d | Matrix-vector product using symmetric band matrix |
cblas_?spmv | s, d | Matrix-vector product using a symmetric packed matrix |
cblas_?spr | s, d | Rank-1 update of a symmetric packed matrix |
cblas_?spr2 | s, d | Rank-2 update of a symmetric packed matrix |
cblas_?symv | s, d | ベクタと対称行列の積を計算します. |
cblas_?syr | s, d | 列ベクタとその転置の積(対称行列のランク1更新)を計算します. |
cblas_?syr2 | s, d | 対称行列のランク2更新を計算します. |
cblas_?tbmv | s, d, c, z | Matrix-vector product using a triangular band matrix |
cblas_?tbsv | s, d, c, z | Linear solution of a triangular band matrix |
cblas_?tpmv | s, d, c, z | Matrix-vector product using a triangular packed matrix |
cblas_?tpsv | s, d, c, z | Linear solution of a triangular packed matrix |
cblas_?trmv | s, d, c, z | ベクタと三角行列の積を計算します. |
cblas_?trsv | s, d, c, z | 三角行列の線型方程式の求解を行ないます. |
ルーチン名を注意深く見ると分かりますが, 同じ処理内容のルーチンが行列の型に合わせて複数存在します. 例えばcblas_?gemvは General Matrix に対する Matrix-vector productの意味です. 同じ処理内容のルーチンが帯行列,対称行列,三角行列向けに存在することが分かります.
ベクタと一般行列の積を計算します.引数を指定することで行列を(共役)転置して演算に供することができます.
cblas_sgemv(),cblas_dgemv(),cblas_cgemv(),cblas_zgemv()
void cblas_dgemv(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const int M, const int N, const double alpha, const double *A, const int lda, const double *X, const int incX, const double beta, double *Y, const int incY);
戻り値はありません.
列ベクタと行ベクタの積を計算します.演算結果が行列になることに注意してください.
cblas_sger(),cblas_dger()
void cblas_dger(const enum CBLAS_ORDER Order, const int M, const int N, const double alpha, const double *X, const int incX, const double *Y, const int incY, double *A, const int lda);
戻り値はありません.
ベクタと対称行列の積を計算します.引数を指定することで行列の上三角部分(下三角部分)のみを演算に供することができます. 必ずサンプルコードに目を通してください.
cblas_ssymv(),cblas_dsymv()
void cblas_dsymv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, const double alpha, const double *A, const int lda, const double *X, const int incX, const double beta, double *Y, const int incY);
戻り値はありません.
列ベクタとその転置の積を計算します.演算結果が対称行列になることに注意してください. 必ずサンプルコードに目を通してください.
cblas_ssyr(),cblas_dsyr()
void cblas_dsyr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, const double alpha, const double *X, const int incX, double *A, const int lda);
戻り値はありません.
対称行列のランク2更新を計算します.演算結果も対称行列になることに注意してください. 必ずサンプルコードに目を通してください.
cblas_ssyr2(),cblas_dsyr2()
void cblas_dsyr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, const double alpha, const double *X, const int incX, const double *Y, const int incY, double *A, const int lda);
戻り値はありません.
ベクタと三角行列の積を計算します.引数を指定することで行列の上三角部分(下三角部分)のみを演算に供することができます. また,同様に引数を指定することで行列を(共役)転置して演算に供することができます. 必ずサンプルコードに目を通してください.
cblas_strmv(),cblas_dtrmv(),cblas_ctrmv(),cblas_ztrmv()
void cblas_dtrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int N, const double *A, const int lda, double *X, const int incX);
戻り値はありません.
三角行列の線型方程式の求解を行ないます.引数を指定することで行列の上三角部分(下三角部分)のみを演算に供することができます. また,同様に引数を指定することで行列を(共役)転置して求解を行なうことができます. 必ずサンプルコードに目を通してください.
cblas_strsv(),cblas_dtrsv(),cblas_ctrsv(),cblas_ztrsv()
void cblas_dtrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int N, const double *A, const int lda, double *X, const int incX);
戻り値はありません.
Level 3 BLASは行列─行列演算ルーチンを提供します. 左辺値の計算対象が右辺にも存在するのはLevel 2 BLASと同様です. 演算に供されるベクタや行列の内,必ず一つの値が失われることを覚えておいてください.
ルーチンの説明は提供される精度を挙げたあと, 最も良く利用すると思われる精度のルーチンについて引数と戻り値を解説します.
Level 3 BLASの全ルーチンを表にします.
ルーチン名 | 精度と型 | 演算の内容 |
---|---|---|
cblas_?gemm | s, d, c, z | 一般行列同士の積を計算します. |
cblas_?hemm | c, z | Matrix-matrix product of Hermitian matrices |
cblas_?herk | c, z | Rank-k update of Hermitian matrices |
cblas_?her2k | c, z | Rank-2k update of Hermitian matrices |
cblas_?symm | s, d, c, z | Matrix-matrix product of symmetric matrices |
cblas_?syrk | s, d, c, z | 行列のランクk更新を計算します |
cblas_?syr2k | s, d, c, z | 行列のランク2k更新を計算します |
cblas_?trmm | s, d, c, z | 三角行列と一般行列の積を計算します. |
cblas_?trsm | s, d, c, z | 三角行列の行列方程式の求解を行ないます |
一般行列同士の積を計算します. (エルミート)転置が行なわれる場合,引数M,N,Kは 転置後の行数,列数を指定します,この場合においても 引数lda,ldb,ldcは元の行数を指定することに注意してください. 転置演算を行なう場合は必ずサンプルコードに目を通してください.
cblas_sgemm(),cblas_dgemm(),cblas_cgemm(),cblas_zgemm()
void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc);
戻り値はありません.
行列のランクk更新を計算します. 転置の有無に関わらず,引数ldaは元の行数を指定することに注意してください. 必ずサンプルコードに目を通してください.
cblas_ssyrk(),cblas_dsyrk(),cblas_csyrk(),cblas_zsyrk()
void cblas_dsyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE Trans, const int N, const int K, const double alpha, const double *A, const int lda, const double beta, double *C, const int ldc);
戻り値はありません.
行列のランク2k更新を計算します. 転置の有無に関わらず,引数lda,ldbは元の行数を指定することに注意してください. 必ずサンプルコードに目を通してください.
cblas_ssyr2k(),cblas_dsyr2k(),cblas_csyr2k(),cblas_zsyr2k()
void cblas_dsyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE Trans, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc);
戻り値はありません.
三角行列と一般行列の積を計算します.
cblas_strmm(),cblas_dtrmm(),cblas_ctrmm(),cblas_ztrmm()
void cblas_dtrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb);
戻り値はありません.
三角行列の行列方程式の求解を行ないます.
cblas_strsm(),cblas_dtrsm(),cblas_ctrsm(),cblas_ztrsm()
void cblas_dtrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb);
戻り値はありません.
ライブラリの詳細を以下に示します.Lapack関係のライブラリもついでに挙げておきます.
ライブラリ名 | 最適化の有無 | 備考 |
---|---|---|
libblas.so | × | Fortranコンパイラによって生成されたオブジェクト.Fortranで実装された標準的なBLAS. |
libcblas.so | - | ATLASの最適化BLASへのインターフェース.リンク時にlibatlas.soが必要 |
libf77blas.so | - | ATLASの最適化BLASをFortran風に使う場合のインターフェース.リンク時にlibf2c.so,libatlas.soが必要 |
libatlas.so | ○ | ATLASの最適化BLASの実体.Cで実装されている. |
liblapack.so | × | Fortranコンパイラによって生成されたオブジェクト.Fortranで実装された標準的なLAPACK. |
libalapack.so | ○ | リンク時にlibf2c.so,libatlas.soが必要,FreeBSD. |
liblapack_atlas.so | ○ | リンク時にlibf2c.so,liblapack.so,libatlas.soが必要,Debian GNU/Linux. |
以上をまとめると,ATLASを用いる場合はライブラリのリンクを以下のように行なえば良いということになります. FreeBSD(上),Debian GNU/Linux(下)です.
-lalapack -lf77blas -lcblas -latlas -lf2c -lm
-llapack_atlas -llapack -lf77blas -lcblas -latlas -lf2c -lm
しかしながら,ATLASはコンパイル時にgccに対して-ffast-mathオプションを指定することがあるようです. ATLASを用いたところ,精度が悪化した,等のことがあった場合は汎用のBLAS,LAPACKを利用すべきかもしれません. 実際,FreeBSDではリンクするライブラリによって計算結果が異なる場合があります.
サンプルコードを置いておきます.適当なところで展開するとMakefileと以下のソースコードが展開されます.
general.c
special.c
disp_array.c
ここで,disp_array.c
は行列の表示のためのモジュールです.
general.c
は一般行列,ベクタに関するサンプルコードです.
special.c
は対称行列,三角行列の演算に関するサンプルコードです.
詳しくはコード中のコメントを読んでください.
本マニュアルは不完全です,改訂を歓迎します.