GeMM
GeMM
GeMM(通用矩阵乘法)方法实现了两个矩阵的一般乘法。 运算定义为 C ← α A B + β C,其中 A 和 B 矩阵可以选择转置。 配合矩阵 AB(MatMul)的正态乘法,假定 alpha 标量等于 1,beta 等于零。
GeMM 和 MatMul 在效率方面的主要区别在于,MatMul 总是创建一个新的矩阵/矢量对象,而 GeMM 使用现有的矩阵对象,且不会重新创建它。 因此,当您使用 GeMM 并为相应的矩阵预分配内存时,在操控相同的矩阵大小时,将不会重新分配内存。 这可能是 GeMM 在批量计算方面的一个重要优势,例如,在策略测试器中运行优化、或训练神经网络时。
与 MatMul 类似,GeMM 也有 4 个重载。 然而,第四次重载的语义已被修改,以便能够将垂直向量与水平向量相乘。
在现有的矩阵/矢量对象中,没有必要预先分配内存。 将在第一次调用 GeMM 时分配内存,并以零填充。
矩阵乘以矩阵: matrix C[M][N] = α * ( matrix A[M][K] * matrix B[K][N]) + β * matrix C[M][N]
bool matrix::GeMM(
const matrix &A, // first matrix
const matrix &B, // second matrix
double alpha, // 乘积 AB 的 alpha 乘数
double beta, // beta multiplier for matrix C
uint flags // a combination of ENUM_GEMM values (bitwise OR), which determines whether matrices A, B and C are transposed
);向量乘以矩阵: vector C[N] = α * ( vector A[K] * matrix B[K][N]) + β * vector C[N]
bool vector::GeMM(
const vector &A, // 水平向量
const matrix &B, // 矩阵
double alpha, // 乘积 AB 的 alpha 乘数
double beta, // 向量 C 的 beta 乘数
uint flags // ENUM_GEMM 枚举值,判定是否矩阵 A 是转置
);矩阵乘以向量: vector C[M] = α * ( matrix A[M][K] * vector B[K] * ) + β * vector C[M]
bool vector::GeMM(
const matrix &A, // 矩阵
const vector &B, // 垂直向量
double alpha, // 乘积 AB 的 alpha 乘数
double beta, // 向量 C 的 beta 乘数
uint flags // ENUM_GEMM 枚举值,判定是否矩阵 B 是转置
);向量乘以向量:matrix C[M][N] = α * ( vector A[M] * vector B[N] * ) + β * matrix C[M][N]. 此重载返回一个矩阵,与 MatMul 不同,它返回一个标量。
bool matrix::GeMM(
const vector &A, // 第一个向量
const vector &B, // 第二个向量
double alpha, // 乘积 AB 的 alpha 乘数
double beta, // 用于矩阵 C 的 beta
uint flags // ENUM_GEMM 枚举值,判定是否矩阵 C 是转置
);参数
- A
[输入] 矩阵或向量。
- B
[输入] 矩阵或向量。
- alpha
[输入] AB 乘积的阿尔法乘数。
- beta
[输入] 所得 C 矩阵的贝塔乘数。
- flags
[输入] 确定是否转置矩阵 A、B 和 C 的 ENUM_GEMM 枚举值。
返回值
成功返回 true,否则 false。
ENUM_GEMM
GeMM 方法的标志枚举。
| ID | 说明 |
|---|---|
| TRANSP_A | 使用转置矩阵 A |
| TRANSP_B | 使用转置矩阵 B |
| TRANSP_C | 使用转置矩阵 C |
注意
浮点型、双精度型和复数类型的矩阵和向量可以用作参数 A 和 B。GeMM 方法的模板变体如下:
bool matrix<T>::GeMM(const matrix<T> &A,const matrix<T> &B,T alpha,T beta,ulong flags);
bool matrix<T>::GeMM(const vector<T> &A,const vector<T> &B,T alpha,T beta,ulong flags);
bool vector<T>::GeMM(const vector<T> &A,const matrix<T> &B,T alpha,T beta,ulong flags);
bool vector<T>::GeMM(const matrix<T> &A,const vector<T> &B,T alpha,T beta,ulong flags);基本上一般的矩阵乘法函数描述为:
C[m,n] = α *Sum(A[m,k]*B[k,n]) + β*C[m,n]配合以下尺寸:矩阵 A 为 M x K,矩阵 B 为 K x N,矩阵 C 为 M x N。
因此,矩阵应该与乘法兼容,即第一个矩阵中的列数应等于第二个矩阵中的行数。 矩阵乘法不支持交换律:在一般情况下,将第一个矩阵乘以第二个矩阵的结果不等于将第二个矩阵乘以第一个矩阵的结果。
示例:
void OnStart()
{
vector vector_a= {1, 2, 3, 4, 5};
vector vector_b= {4, 3, 2, 1};
matrix matrix_c;
//--- 计算两个向量的 GeMM
matrix_c.GeMM(vector_a, vector_b, 1, 0);
Print("matrix_c:\n ", matrix_c, "\n");
/*
matrix_c:
[[4,3,2,1]
[8,6,4,2]
[12,9,6,3]
[16,12,8,4]
[20,15,10,5]]
*/
//--- 创建矩阵作为向量
matrix matrix_a(5, 1);
matrix matrix_b(1, 4);
matrix_a.Col(vector_a, 0);
matrix_b.Row(vector_b, 0);
Print("matrix_a:\n ", matrix_a);
Print("matrix_b:\n ", matrix_b);
/*
matrix_a:
[[1]
[2]
[3]
[4]
[5]]
matrix_b:
[[4,3,2,1]]
*/
//-- 计算两个矩阵的 GeMM 并获取相同的结果
matrix_c.GeMM(matrix_a, matrix_b, 1, 0);
Print("matrix_c:\n ", matrix_c);
/*
matrix_c:
[[4,3,2,1]
[8,6,4,2]
[12,9,6,3]
[16,12,8,4]
[20,15,10,5]]
*/
}