GeMM

O método GeMM determina o produto matricial total de duas matrizes (General Matrix Multiply). Em termos gerais, a expressão é escrita como C ← α A B + β C , onde as matrizes A e B podem ser opcionalmente transpostas. Ao realizar a multiplicação convencional de matrizes AB (MatMul), é assumido que o coeficiente alpha é igual a um e o beta é igual a zero.

A principal diferença entre GeMM e MatMul em termos de eficiência é que MatMul sempre cria um novo objeto matriz/vetor, enquanto GeMM trabalha com um objeto matriz já existente que não é recriado. Dessa forma, se a memória para a matriz correspondente for alocada com antecedência ao usar o método GeMM e as mesmas dimensões de matriz forem usadas posteriormente, não haverá realocação de memória. Isso pode ser uma vantagem muito importante para o método GeMM em computações em massa, como na otimização em um testador de estratégia ou no treinamento de uma rede neural.

GeMM também possui 4 sobrecargas, assim como o método MatMul. Mas, nesse caso, a semântica da quarta sobrecarga foi alterada para permitir a multiplicação de vetores verticais e horizontais.

Em um objeto de matriz/vetor existente, não é necessário alocar memória para dados com antecedência. Na primeira vez que o GeMM for chamado, a memória será alocada e preenchida com zeros.

Multiplicação de uma matriz por uma matriz:   matrix C[M][N] = α * ( matrix A[M][K] * matrix B[K][N]) + β * matrix C[M][N]

bool  matrix::GeMM(
  const matrix &A,    // primeira matriz
  const matrix &B,    // segunda matriz
  double alpha,       // multiplicador alfa para o produto das matrizes AB
  double beta,        // multiplicador beta para a matriz C
  uint   flags        // combinação de valores de enumeração ENUM_GEMM (bits "ou"), que determina a transposição das matrizes A, B e C
   );

Multiplicação de um vetor por uma matriz: vector C[N] = α * ( vector A[K] * matrix B[K][N]) + β * vector C[N]

bool  vector::GeMM(
  const vector &A,    // vetor horizontal 
  const matrix &B,    // matriz
  double alpha,       // multiplicador alfa para o produto AB
  double beta,        // multiplicador beta para o vetor C
  uint   flags        // valor da enumeração ENUM_GEMM que determina a transposição da matriz B
   );

Multiplicação de uma matriz por um vetor: vector C[M] = α * ( matrix A[M][K] * vector B[K] * ) + β * vector C[M]

bool  vector::GeMM(
  const matrix &A,    // matriz
  const vector &B,    // vetor vertical
  double alpha,       // multiplicador alfa para o produto AB
  double beta,        // multiplicador beta para o vetor C
  uint   flags        // valor da enumeração ENUM_GEMM que determina a transposição de A
   );

Multiplicação de um vetor por um vetor: matrix C[M][N] = α * ( vector A[M] * vector B[N] * ) + β * matrix C[M][N]. Esta sobrecarga retorna uma matriz, ao contrário do método MatMul, que retorna um escalar.

bool  matrix::GeMM(
  const vector &A,    // primeiro vetor
  const vector &B,    // segundo vetor
  double alpha,       // multiplicador alfa para o produto AB
  double beta,        // multiplicador beta para a matriz C
  uint   flags        // valor da enumeração ENUM_GEMM que determina a transposição da matriz C
   );

Parâmetros

A

[in]  Matriz ou vetor.

B

[in]  Matriz ou vetor.

alpha

[in]  Multiplicador alfa para o produto AB.

beta

[in]  Multiplicador Beta para a matriz resultante C.

flags

[in]  Valor da enumeração ENUM_GEMM que determina a transposição das matrizes A, B e C.

Valor retornado

true se a operação for bem sucedida, caso contrário false.

ENUM_GEMM

Enumeração de sinalizadores para o método GeMM.

Identificador

Descrição

TRANSP_A

Uso da matriz transposta A

TRANSP_B

Uso da matriz transposta B

TRANSP_C

Uso da matriz transposta C

Observação

Matrizes e vetores do tipo float, double e complex podem ser usados como parâmetros A e B. Assim, as variantes de modelo do método GeMM têm este aspecto:

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

Em geral, uma função de multiplicação geral da matriz é descrita como:

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

onde a matriz A é do tamanho M x K, a matriz B é K x N, e a matriz C é M x N.

Assim, as matrizes multiplicadas devem ser compatíveis, o número de colunas da primeira matriz deve ser igual ao número de linhas da segunda matriz. A multiplicação de matrizes não é comutativa, a multiplicação da primeira matriz pela segunda não é igual à multiplicação da segunda matriz pela primeira.

 

Exemplo:

void OnStart()
  {
   vector vector_a= {12345};
   vector vector_b= {4321};
   matrix matrix_c;
//--- calculamos GeMM para dois vetores
   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]]
   */
//--- criamos matrizes sob a forma de vetores
   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 as duas matrizes e obtemos o mesmo 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 também

MatMul