Moltiplica due matrici in C++

Jinku Hu 12 ottobre 2023
Moltiplica due matrici in C++

Questo articolo spiegherà diversi metodi su come moltiplicare due matrici in C++.

Usa l’implementazione seriale per moltiplicare due matrici in C++

La moltiplicazione di matrici è una delle operazioni più comunemente utilizzate in un’ampia gamma di soluzioni ingegneristiche. Pertanto, esistono vari algoritmi per migliorare le prestazioni su diverse piattaforme hardware. Questi algoritmi utilizzano spesso la programmazione simultanea e l’affiancamento di matrici per accelerare la moltiplicazione di matrici. In questo caso, tuttavia, implementiamo un algoritmo semplice che viene eseguito in serie senza ottimizzazioni esplicite.

All’inizio, abbiamo bisogno di implementare alcune funzioni di utilità per aiutare ad allocare e inizializzare le matrici con cui operare. Notare che stiamo implementando il codice in modo che il programmatore possa modificare gli interi costanti ROW e COL per specificare le dimensioni della matrice. La funzione allocateMatrix alloca l’array di array e inizializza gli elementi con valori zero. Successivamente, viene chiamata la funzione initilizeMatrix che genera numeri casuali nell’intervallo - [0, 100) e li memorizza come elementi di matrice. Si noti che esiste anche una funzione che stampa gli elementi della matrice nel flusso cout per verificare i risultati del calcolo.

La funzione multiplyMatrix implementa un semplice cicli for triplo annidato per moltiplicare due matrici e memorizzare i risultati nella terza matrice preallocata. Le dimensioni della matrice dei risultati vengono prese dalle prime righe della matrice e dalle seconde colonne della matrice. Tieni presente che l’ordine del bucle è abbastanza importante per le prestazioni di moltiplicazione. Ad esempio, se spostiamo la dichiarazione for più interna nel mezzo, ci si aspetta un aumento delle prestazioni quasi garantito. Il miglioramento delle prestazioni è causato dalle memorie cache che si trovano in quasi tutte le CPU contemporanee. La memoria cache è più veloce della memoria principale e archivia blocchi di memoria contigui quando i dati vengono recuperati. Pertanto, il successivo recupero dei dati può essere servito dalle cache stesse.

#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;
}

Produzione:

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

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

16126; 11521;
8017;  4278;

Infine, è importante liberare tutte le risorse di memoria utilizzate dalle matrici prima che il programma esca. La funzione deallocateMatrix è implementata in modo che richieda un puntatore a matrice e righe in esso per eliminare ogni elemento nell’oggetto. Si noti che anche la matrice dei risultati allocata nell’ambito della funzione multiplyMatrix dovrebbe essere deallocata esplicitamente.

Autore: 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

Articolo correlato - C++ Math