GeMM

Метод GeMM реализует общее матричное произведение двух матриц (General Matrix Multiply). В общем виде выражение записывается как  C ← α A B + β C , где матрицы A и B могут быть необязательно транспонированы. При обычном умножении матриц AB (MatMul ) предполагается, что коэффициент alpha равен единице, а beta - нулю.

Главное отличие GeMM от MatMul с точки зрения эффективности, состоит в том, что MatMul всегда создаёт новый объект матрицы/вектора, в то время как GeMM работает с уже существующим объектом матрицы, который не пересоздаётся. Поэтому, если при использовании с GeMM заранее распределить память для соответствующей матрицы и работать потом с одними и теми же размерами матриц, то не будет никакого перераспределения памяти. Это может быть очень важным преимуществом в пользу GeMM при массовых вычислениях, например, при оптимизации в тестере стратегий или тренировке нейронной сети.

У GeMM также 4 перегрузки, как и у метода  MatMul. Но при этом семантика 4-й перегрузки была изменена для того, чтобы можно было перемножать вертикальные и горизонтальные векторы.

В существующем объекте матрицы/вектора необязательно заранее распределять память под данные. При первом вызове GeMM память будет распределена и заполнена нулями.

Умножение матрицы на матрицу:   matrix C[M][N] = α * ( matrix A[M][K] * matrix B[K][N]) + β * matrix C[M][N]

bool  matrix::GeMM(
  const matrix &A,    // первая матрица
  const matrix &B,    // вторая  матрица
  double alpha,       // множитель альфа для произведения матриц AB
  double beta,        // множитель бета для матрицы C
  uint   flags        // комбинация значений перечисления ENUM_GEMM (битовое "или"), которое определяет транспонированность матриц A, B и С
   );

Умножение вектора на матрицу: 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
  double beta,        // множитель бета для вектора C
  uint   flags        // значение перечисления ENUM_GEMM,  которое определяет транспонированность матрицы B
   );

Умножение матрицы на вектор: 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
  double beta,        // множитель бета для вектора C
  uint   flags        // значение перечисления ENUM_GEMM,  которое определяет транспонированность A
   );

Умножение вектора на вектор: 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
  double beta,        // множитель бета для матрицы C
  uint   flags        // значение перечисления ENUM_GEMM,  которое определяет транспонированность матрицы С
   );

Параметры

A

[in]  Матрица или вектор.

B

[in]  Матрица или вектор.

alpha

[in]  Множитель альфа для произведения AB.

beta

[in]  Множитель бета для результирующей матрицы C.

flags

[in]  Значение перечисления ENUM_GEMM,  которое определяет транспонированность матриц A, B и С.

Возвращаемое значение

true в случае успешного выполнения операции, иначе false.

ENUM_GEMM

Перечисление флагов для метода GeMM.

Идентификатор

Описание

TRANSP_A

Использовать транспонированную матрицу A

TRANSP_B

Использовать транспонированную матрицу B

TRANSP_C

Использовать транспонированную матрицу C

Примечание

В качестве параметров A и B могут использоваться матрицы и векторы типа float, double и complex. Таким образом, шаблонные варианты метода 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 х K, матрица B — K х N, и матрица C — M х N.

Таким образом, перемножаемые матрицы должны быть совместимы, количество столбцов первой матрицы должно быть равно количеству строк второй матрицы. Перемножение матриц некоммутативно, умножение первой матрицы на вторую в общем случае не равно умножению второй матрицы на первую.

 

Пример:

void OnStart()
  {
   vector vector_a= {12345};
   vector vector_b= {4321};
   matrix matrix_c;
//--- вычислим GeMM для двух векторов
   matrix_c.GeMM(vector_avector_b10);
   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(51);
   matrix matrix_b(14);
   matrix_a.Col(vector_a0);
   matrix_b.Row(vector_b0);
   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_amatrix_b10);
   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]]
   */
  }

 

Смотри также

MatMul