Multiplizieren zweier Matrizen in C++

Jinku Hu 12 Oktober 2023
Multiplizieren zweier Matrizen in C++

In diesem Artikel werden verschiedene Methoden zum Multiplizieren von zwei Matrizen in C++ erläutert.

Verwenden der seriellen Implementierung zum Multiplizieren von zwei Matrizen in C++

Die Matrixmultiplikation ist eine der am häufigsten verwendeten Operationen in einer Vielzahl von technischen Lösungen. Daher gibt es verschiedene Algorithmen, um die Leistung auf verschiedenen Hardwareplattformen zu verbessern. Diese Algorithmen verwenden häufig die gleichzeitige Programmierung sowie Matrixkacheln, um die Matrixmultiplikation zu beschleunigen. In diesem Fall implementieren wir jedoch einen einfachen Algorithmus, der seriell ohne explizite Optimierungen ausgeführt wird.

Zunächst müssen einige Dienstprogrammfunktionen implementiert werden, um die Zuordnung und Initialisierung von Matrizen für den Betrieb zu erleichtern. Beachten Sie, dass wir den Code so implementieren, dass der Programmierer die konstanten Ganzzahlen ROW und COL ändern kann, um die Matrixdimensionen anzugeben. Die Funktion allocateMatrix ordnet das Array von Arrays zu und initialisiert Elemente mit Nullwerten. Als nächstes wird die Funktion initilizeMatrix aufgerufen, die Zufallszahlen im Bereich [0, 100) generiert und als Matrixelemente speichert. Beachten Sie, dass es auch eine Funktion gibt, die die Matrixelemente in den Stream cout druckt, um die Berechnungsergebnisse zu überprüfen.

Die Funktion multiplyMatrix implementiert eine einfache dreifach verschachtelte for-Schleife, um zwei Matrizen zu multiplizieren und die Ergebnisse in der vorab zugewiesenen dritten Matrix zu speichern. Die Ergebnismatrixdimensionen werden aus den ersten Matrixzeilen und den zweiten Matrixspalten entnommen. Beachten Sie, dass die Schleifenreihenfolge für die Multiplikationsleistung sehr wichtig ist. Wenn wir beispielsweise die innerste for-Anweisung in die Mitte verschieben, wird ein fast garantierter Leistungsschub erwartet. Die Leistungsverbesserung wird durch die Cache-Speicher verursacht, die sich in fast jeder modernen CPU befinden. Der Cache-Speicher ist schneller als der Hauptspeicher und speichert zusammenhängende Speicherblöcke, wenn die Daten abgerufen werden. Somit kann der nächste Datenabruf aus den Caches selbst bedient werden.

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

Ausgabe:

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

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

16126; 11521;
8017;  4278;

Schließlich ist es wichtig, alle von den Matrizen verwendeten Speicherressourcen freizugeben, bevor das Programm beendet wird. Die Funktion deallocateMatrix ist so implementiert, dass ein Matrixzeiger und Zeilen darin erforderlich sind, um jedes Element im Objekt zu löschen. Beachten Sie, dass die im Funktionsbereich multiplyMatrix zugewiesene Ergebnismatrix ebenfalls explizit freigegeben werden sollte.

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

Verwandter Artikel - C++ Math