Multiplique duas matrizes em C++

Jinku Hu 12 outubro 2023
Multiplique duas matrizes em C++

Este artigo explicará vários métodos de como multiplicar duas matrizes em C++.

Use a implementação serial para multiplicar duas matrizes em C++

A multiplicação de arrayes é uma das operações mais comumente usadas em uma ampla gama de soluções de engenharia. Assim, existem vários algoritmos para melhorar o desempenho em diferentes plataformas de hardware. Esses algoritmos geralmente utilizam programação simultânea, bem como tiling de array para acelerar a multiplicação de arrayes. Nesse caso, porém, implementamos um algoritmo direto que é executado em série sem nenhuma otimização explícita.

Primeiramente, precisamos implementar algumas funções utilitárias para ajudar a alocar e inicializar matrizes com as quais operar. Observe que estamos implementando o código para que o programador possa modificar os inteiros constantes ROW e COL para especificar as dimensões do array. A função allocateMatrix aloca o array de arrays e inicializa os elementos com valores zero. Em seguida, a função initilizeMatrix é chamada e gera números aleatórios no intervalo - [0, 100) e os armazena como elementos de array. Observe que também há uma função que imprime os elementos do array no fluxo cout para verificar os resultados do cálculo.

A função multiplyMatrix implementa um loop for aninhado triplo simples para multiplicar duas matrizes e armazenar os resultados na terceira matriz pré-alocada. As dimensões do array de resultado são obtidas das primeiras linhas do array e das segundas colunas do array. Lembre-se de que a ordem do loop é muito importante para o desempenho da multiplicação. Por exemplo, se movermos a instrução for mais interna no meio, há um aumento de desempenho quase garantido esperado. A melhoria de desempenho é causada pelas memórias cache que estão localizadas em quase todas as CPUs contemporâneas. A memória cache é mais rápida do que a memória principal e armazena blocos de memória contíguos quando os dados são recuperados. Assim, a próxima recuperação de dados pode ser servida a partir dos próprios caches.

#include <iomanip>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::setw;
using std::vector;

constexpr int ROW = 2;
constexpr int COL = 3;

void initilizeMatrix(int **m, int row, int col) {
  for (auto i = 0; i < row; ++i) {
    for (auto j = 0; j < col; ++j) {
      m[i][j] = rand() % 100;
    }
  }
}

void printMatrix(int **m, int row, int col) {
  for (auto i = 0; i < row; ++i) {
    for (auto j = 0; j < col; ++j) {
      cout << setw(5) << m[i][j] << "; ";
    }
    cout << endl;
  }
}

int **allocateMatrix(int row, int col) {
  int **matrix = new int *[row];
  for (int i = 0; i < row; ++i) {
    matrix[i] = new int[col]{0};
  }
  return matrix;
}

int deallocateMatrix(int **matrix, int row) {
  for (int i = 0; i < row; ++i) {
    delete matrix[i];
  }
  delete[] matrix;
  return 0;
}

int **multiplyMatrix(int **m1, int row1, int col1, int **m2, int row2,
                     int col2) {
  if (col1 != row2) return nullptr;

  auto ret = allocateMatrix(row1, col2);

  int i, j, k;

  for (i = 0; i < row1; i++) {
    for (j = 0; j < col2; j++) {
      for (k = 0; k < col1; k++) {
        ret[i][j] += m1[i][k] * m2[k][j];
      }
    }
  }

  return ret;
}

int main() {
  int **matrix1 = allocateMatrix(ROW, COL);
  int **matrix2 = allocateMatrix(COL, ROW);

  initilizeMatrix(matrix1, ROW, COL);
  initilizeMatrix(matrix2, COL, ROW);

  printMatrix(matrix1, ROW, COL);
  cout << endl;
  printMatrix(matrix2, COL, ROW);

  auto result = multiplyMatrix(matrix1, ROW, COL, matrix2, COL, ROW);

  cout << endl;
  printMatrix(result, ROW, ROW);

  deallocateMatrix(matrix1, ROW);
  deallocateMatrix(matrix2, COL);
  deallocateMatrix(result, ROW);

  return EXIT_SUCCESS;
}

Resultado:

83;    86;    77;
15;    93;    35;

86;    92;
49;    21;
62;    27;

16126; 11521;
8017;  4278;

Finalmente, é importante liberar todos os recursos de memória usados ​​pelas matrizes antes de encerrar o programa. A função deallocateMatrix é implementada de forma que pegue um ponteiro de array e linhas nele para excluir cada elemento no objeto. Observe que a matriz de resultados alocada no escopo da função multiplicaçãoMatriz também deve ser desalocada explicitamente.

Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C++ Math