?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の値を渡しても自動的に昇格されるので)