?GEMM_
List
sgemm_ | cblas_sgemm | 単精度実 数一般行列と一般行列の積 |
dgemm_ | cblas_dgemm | 倍精度実 数一般行列と一般行列の積 |
cgemm_ | cblas_cgemm | 単精度複素数一般行列と一般行列の積 |
zgemm_ | cblas_zgemm | 倍精度複素数一般行列と一般行列の積 |
概略
一般行列と一般行列の積を計算します。結果を別途渡した行列にスカラ倍したものを加算します(詳しくは計算式参照)計算式
C := alpha * AB + beta * Cbeta=0のときは、Cへは単なる代入を行います。
サンプルコード
通常の実数の例#include <cblas.h> #include <stdio.h> int main(void) { double A[2*3]={1.0,2.0,3.0, 4.0,5.0,6.0}; double B[3*4]={1.0,2.0,3.0,4.0, 5.0,6.0,7.0,8.0, 9.0,0.0,1.0,2.0}; double C[2*4]; //x * y = 38 14 20 26 // 83 38 53 68 となることを確かめる //二次元配列の場合 //double A[2][3]={{1.0,2.0,3.0}, // {4.0,5.0,6.0}}; //のように二次元配列で定義しても以下は同じコードで動く //double B[3][4]={{1.0,2.0,3.0,4.0}, // {5.0,6.0,7.0,8.0}, // {9.0,0.0,1.0,2.0}}; //double C[2][4]; int i,j; cblas_dgemm(CblasRowMajor,//通常のCの行列であればCBlasRowMajorを指定 CblasNoTrans, //Aについて転置しない場合 CblasNoTrans 転置する場合 CblasTrans CblasNoTrans, //Bについて転置しない場合 CblasNoTrans 転置する場合 CblasTrans 2, //Aの行数 4, //Bの列数 3, //Aの列数 = Bの行数(一致していないと掛け算できない) 1, //alpha の値 A, //A 3, //leading dimension (通常はAの列数) B, //B 4, //leading dimension (通常はBの列数) 0, //beta の値 C, //C 4 //leading dimension (通常はCの列数) ); for(i=0;i<2;i++){ for(j=0;j<4;j++){ //二次元配列の場合でもこの書き方でOK printf("%lf ",C[i*4+j]); //(i,j)成分は i*ldC+jの形で書ける ldCはCのleading dimension :Cの列数 //printf("%lf ",C[i][j]);//もちろん、二次元配列で定義すればこれでも動く } printf("\n"); } return 0; }転置する場合の例
#include <cblas.h> #include <stdio.h> int main(void) { double A[3*2]={1.0,2.0, 3.0,4.0, 5.0,6.0}; double B[4*3]={1.0,2.0,3.0, 4.0,5.0,6.0, 7.0,8.0,9.0, 0.0,1.0,2.0}; double C[2*4]; //x * y = 22 49 76 13 // 28 64 100 16 となることを確かめる int i,j; cblas_dgemm(CblasRowMajor,//通常のCの行列であればCBlasRowMajorを指定 CblasTrans, //Aについて転置しない場合 CblasNoTrans 転置する場合 CblasTrans CblasTrans, //Bについて転置しない場合 CblasNoTrans 転置する場合 CblasTrans 2, //Aの行数(転置後) 4, //Bの列数(転置後) 3, //Aの列数(転置後) = Bの行数(転置後)(一致していないと掛け算できない) 1, //alpha の値 A, //A 2, //leading dimension (通常はAの列数(転置前)) B, //B 3, //leading dimension (通常はBの列数(転置前)) 0, //beta の値 C, //C 4 //leading dimension (通常はCの列数) ); for(i=0;i<2;i++){ for(j=0;j<4;j++){ printf("%lf ",C[i*4+j]); //(i,j)成分は i*ldC+jの形で書ける ldCはCのleading dimension :Cの列数 } printf("\n"); } return 0; }
複素数の例
#include <cblas.h> #include <stdio.h> typedef struct { double r; double i; } complex_; int main(void) { //複素数を構造体無しで扱う場合はaxpyを参照 complex_ A[2][2]={{{1.0,2.0},{3.0,4.0}}, // 1+2i 3+4i {{5.0,6.0},{7.0,8.0}}}; // 5+6i 7+8i complex_ B[2][2]={{{8.0,7.0},{6.0,5.0}}, // 8+7i 6+5i {{4.0,3.0},{2.0,1.0}}}; // 4+3i 2+1i complex_ C[2][2]; //x * y =-6 + 48 i, -2 + 28 i // 2 + 136 i, 6 + 84 i となることを確かめる complex_ alpha={1,0}; complex_ beta={0,0}; int i,j; cblas_zgemm(CblasRowMajor,//通常のCの行列であればCBlasRowMajorを指定 CblasNoTrans, //A 転置しない場合 CblasNoTrans 転置 CblasTrans 共役転置 CblasConjTrans CblasNoTrans, //B 転置しない場合 CblasNoTrans 転置 CblasTrans 共役転置 CblasConjTrans 2, //Aの行数 2, //Bの列数 2, //Aの列数 = Bの行数(一致していないと掛け算できない) &alpha, //alpha の値:構造体へのポインタになる A, //A 2, //leading dimension (通常はAの列数) B, //B 2, //leading dimension (通常はBの列数) &beta, //beta の値:構造体へのポインタになる C, //C 2 //leading dimension (通常はCの列数) ); for(i=0;i<2;i++){ for(j=0;j<2;j++){ printf("%lf + %lf i, ",C[i][j].r,C[i][j].i); } printf("\n"); } return 0; }
引数/戻り値
cblas_dgemm
変数名 | 型 | 上書き | 概要 |
Order | enum CBLAS_ORDER | C言語では通常はCBlasRowMajor(列方向に並べる) Fortran式ならCBlasColMajor(行方向に並べる) | |
Transa | enum CBLAS_TRANSPOSE | 行列Aの転置を指定 転置しない CblasNoTrans 転置 CblasTrans 共役転置 CblasConjTrans | |
Transb | enum CBLAS_TRANSPOSE | 行列Bの転置を指定 転置しない CblasNoTrans 転置 CblasTrans 共役転置 CblasConjTrans | |
m | int | 行列Aの行数 | |
n | int | 行列Bの列数 | |
k | int | 行列Aの列数、行列Bの行数 | |
alpha | double | スカラーalpha | |
A | double* | 行列Aの先頭ポインタ | |
ldA | int | Aのleading dimension CBlasRowMajorを指定したら列数 CBlasColMajor指定なら行数 | |
B | double* | 行列Bの先頭ポインタ | |
ldB | int | Bのleading dimension CBlasRowMajorを指定したら列数 CBlasColMajor指定なら行数 | |
beta | double | スカラーbeta | |
C | double* | 上書き | 行列Cの先頭ポインタ |
ldC | int | Cのleading dimension CBlasRowMajorを指定したら列数 CBlasColMajor指定なら行数 | |
戻り値 | void |
dgemm_
変数名 | 型(dgemm_) | 概要 |
transa | char* | 行列Aの転置を指定 ("N"(そのまま),"T"(転置),"C"(共役転置)から選択) |
transb | char* | 行列Bの転置を指定 ("N"(そのまま),"T"(転置),"C"(共役転置)から選択) |
m | int* | 行列Aの行数 |
n | int* | 行列Bの列数 |
k | int* | 行列Aの列数、行列Bの行数 |
alpha | double* | スカラーalpha |
A | double* | 行列Aの先頭ポインタ |
ldA | int* | Aのleading dimension (通常は行数を指定すれば良い) |
B | double* | 行列Bの先頭ポインタ |
ldB | int* | Bのleading dimension (通常は行数を指定すれば良い) |
beta | double* | スカラーbeta |
C | double* | 行列Cの先頭ポインタ |
ldC | int* | Cのleading dimension (通常は行数を指定すれば良い) |
戻り値 | void |
プロトタイプ宣言
void sgemm_(char *transa, char *transb, int *m, int *n, int *k,float *alpha, float *A, int *ldA, float *B, int *ldB,
float *beta , float *C, int *ldC);
void dgemm_(char *transa, char *transb, int *m, int *n, int *k,
double *alpha, double *A, int *ldA, double *B, int *ldB,
double *beta , double *C, int *ldC);
void cgemm_(char *transa, char *transb, int *m, int *n, int *k,
complex *alpha, complex *A, int *ldA, complex *B, int *ldB,
complex *beta , complex *C, int *ldC);
void zgemm_(char *transa, char *transb, int *m, int *n, int *k,
doublecomplex *alpha, doublecomplex *A, int *ldA, doublecomplex *B, int *ldB,
doublecomplex *beta , doublecomplex *C, int *ldC);
void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB,
const blasint M, const blasint N, const blasint K,
const float alpha, const float *A, const blasint lda, const float *B, const blasint ldb, const float beta, float *C, const blasint ldc);
void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB,
const blasint M, const blasint N, const blasint K,
const double alpha, const double *A, const blasint lda, const double *B, const blasint ldb, const double beta, double *C, const blasint ldc);
void cblas_cgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB,
const blasint M, const blasint N, const blasint K,
const void *alpha, const void *A, const blasint lda, const void *B, const blasint ldb, const void *beta, void *C, const blasint ldc);
void cblas_zgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB,
const blasint M, const blasint N, const blasint K,
const void *alpha, const void *A, const blasint lda, const void *B, const blasint ldb, const void *beta, void *C, const blasint ldc);
※OPENBLAS_CONSTはcblas.hにて
# define OPENBLAS_CONST constで定義されているため、ここではconstで置き換えている
※blasintはcommon.hにて
#if defined(OS_WINDOWS) && defined(__64BIT__) typedef long long BLASLONG; typedef unsigned long long BLASULONG; #else typedef long BLASLONG; typedef unsigned long BLASULONG; #endif #ifdef USE64BITINT typedef BLASLONG blasint; #else typedef int blasint; #endifで定義される(不要なコードは除いている)ため、環境により異なる。
初学者は通常はintの別名として定義されると考えて使用しても概ね差し支えない
(Cにおいてはintの値を渡しても自動的に昇格されるので)