GeMM

El método GeMM realiza el producto matricial total de dos matrices (General Matrix Multiply). En términos generales, la expresión se escribe como C ← α A B + β C , donde las matrices A y B pueden transponerse opcionalmente. Cuando las matrices AB se multiplican de forma normal (MatMul ), se presupone que el coeficiente alpha es igual a la unidad, mientras que beta es igual a cero.

La principal diferencia entre GeMM y MatMul en términos de eficiencia es que MatMul siempre crea un nuevo objeto matriz/vector, mientras que GeMM trabaja con un objeto de matriz existente que no se vuelve a crear. Por consiguiente, al utilizarse con GeMM, si asignamos memoria para la matriz correspondiente por adelantado y luego trabajamos con los mismos tamaños de matriz, no habrá reasignación de memoria. Esto puede ser una ventaja muy importante a favor de GeMM en los cálculos masivos, por ejemplo, al optimizar en el simulador de estrategias o entrenar redes neuronales.

GeMM también tiene 4 sobrecargas como el método MatMul. No obstante, la semántica de la 4ª sobrecarga se ha modificado para permitir multiplicar vectores verticales y horizontales.

En un objeto de matriz/vector existente, no será necesario asignar memoria para los datos por adelantado. La primera vez que se llame a GeMM, la memoria será asignada y rellenada con ceros.

Multiplicación de una matriz por una matriz:   matrix C[M][N] = α * ( matrix A[M][K] * matrix B[K][N]) + β * matrix C[M][N]

bool  matrix::GeMM(
  const matrix &A,    // primera matriz
  const matrix &B,    // segunda  matriz
  double alpha,       // multiplicador alfa del producto de matrices AB
  double beta,        // multiplicador beta de la matriz C
  uint   flags        // combinación de valores de la enumeración ENUM_GEMM (de bits "o") que determina la transponibilidad de las matrices A, B y С
   );

Multiplicación de un vector por una matriz: vector C[N] = α * ( vector A[K] * matrix B[K][N]) + β * vector C[N]

bool  vector::GeMM(
  const vector &A,    // vector horizontal 
  const matrix &B,    // matriz
  double alpha,       // multiplicador alfa del producto AB
  double beta,        // multiplicador beta para el vector C
  uint   flags        // valor de la enumeración ENUM_GEMM  que determina la transponibilidad de la matriz B
   );

Multuplicación de una matriz por un vector: vector C[M] = α * ( matrix A[M][K] * vector B[K] * ) + β * vector C[M]

bool  vector::GeMM(
  const matrix &A,    // matriz
  const vector &B,    // vector vertical
  double alpha,       // multiplicador alfa del producto AB
  double beta,        // multiplicador beta para el vector C
  uint   flags        // valor de la enumeración ENUM_GEMM  que determina la transponibilidad de A
   );

Multiplicación de un vector por un vector: matrix C[M][N] = α * ( vector A[M] * vector B[N] * ) + β * matrix C[M][N]. Esta sobrecarga retorna una matriz, a diferencia del método MatMul, que retorna un escalar.

bool  matrix::GeMM(
  const vector &A,    // primer vector
  const vector &B,    // segundo  vector
  double alpha,       // multiplicador alfa del producto AB
  double beta,        // multiplicador beta de la matriz C
  uint   flags        // valor de la enumeración ENUM_GEMM  que determina la transponibilidad de la matriz С
   );

Parámetros

A

[in]  Matriz o vector.

B

[in]  Matriz o vector.

alpha

[in]  Multiplicador alfa para el producto AB.

beta

[in]  Multiplicador beta para la matriz resultante C.

flags

[in]  Valor de la enumeración ENUM_GEMM  que determina la transponibilidad de las matrices A, B y С.

Valor retornado

true si la operación se ha ejecutado con éxito, de lo contrario, false.

ENUM_GEMM

Enumeración de banderas para el método GeMM.

Identificador

Descripción

TRANSP_A

Utilizar la matriz transpuesta A

TRANSP_B

Utilizar la matriz transpuesta B

TRANSP_C

Utilizar la matriz transpuesta C

Observación

Como parámetros A y B podemos utilizar matrices y vectores de tipo float, double y complex. Así, las variantes de plantilla del método GeMM serán las siguientes:

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);

En general, una función general de multiplicación de matrices se describirá como:

C[m,n] = α *Sum(A[m,k]*B[k,n]) + β*C[m,n]

donde la matriz A es de tamaño M x K, la matriz B es K x N, y la matriz C es M x N.

Así, las matrices a multiplicar deberán ser compatibles, el número de columnas de la primera matriz deberá ser igual al número de filas de la segunda matriz. La multiplicación de matrices es no conmutativa: la multiplicación de la primera matriz por la segunda matriz no es en general igual a la multiplicación de la segunda matriz por la primera.

 

Ejemplo:

void OnStart()
  {
   vector vector_a= {12345};
   vector vector_b= {4321};
   matrix matrix_c;
//--- calculamos GeMM para los dos vectores
   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]]
   */
//--- creamos las matrices en forma de vectores
   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]]
   */
//-- calculamos GeMM para las dos matrices y obtemos el mismo resultado
   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]]
   */
  }

 

Ver también

MatMul