Multiplier deux matrices en C++

Jinku Hu 12 octobre 2023
Multiplier deux matrices en C++

Cet article explique plusieurs méthodes de multiplication de deux matrices en C++.

Utiliser l’implémentation série pour multiplier deux matrices en C++

La multiplication matricielle est l’une des opérations les plus couramment utilisées dans un large éventail de solutions d’ingénierie. Ainsi, il existe différents algorithmes pour améliorer les performances sur différentes plates-formes matérielles. Ces algorithmes utilisent souvent la programmation simultanée ainsi que la mosaïque matricielle pour accélérer la multiplication matricielle. Dans ce cas, cependant, nous implémentons un algorithme simple qui s’exécute en série sans aucune optimisation explicite.

Au début, nous devons implémenter certaines fonctions utilitaires pour aider à allouer et initialiser les matrices avec lesquelles fonctionner. Notez que nous implémentons le code pour que le programmeur puisse modifier les entiers constants ROW et COL pour spécifier les dimensions de la matrice. La fonction allocateMatrix alloue le tableau des tableaux et initialise les éléments avec des valeurs nulles. Ensuite, la fonction initilizeMatrix est appelée qui génère des nombres aléatoires dans la plage - [0, 100) et les stocke comme éléments de matrice. Notez qu’il existe également une fonction qui imprime les éléments de la matrice dans le flux cout pour vérifier les résultats du calcul.

La fonction multiplyMatrix implémente une simple boucle for triple emboîtée pour multiplier deux matrices et stocker les résultats dans la troisième matrice préallouée. Les dimensions de la matrice de résultat sont extraites des premières lignes de la matrice et des secondes colonnes de la matrice. Gardez à l’esprit que l’ordre des boucles est assez important pour les performances de multiplication. Par exemple, si nous déplaçons la déclaration for la plus interne au milieu, il y a une augmentation des performances presque garantie attendue. L’amélioration des performances est causée par les mémoires cache qui se trouvent dans presque tous les processeurs contemporains. La mémoire cache est plus rapide que la mémoire principale et stocke des blocs de mémoire contigus lorsque les données sont récupérées. Ainsi, la prochaine récupération de données peut être servie à partir des caches eux-mêmes.

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

Production:

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

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

16126; 11521;
8017;  4278;

Enfin, il est important de libérer toutes les ressources mémoire utilisées par les matrices avant la fermeture du programme. La fonction deallocateMatrix est implémentée de sorte qu’elle prenne un pointeur de matrice et des lignes dedans pour supprimer chaque élément de l’objet. Notez que la matrice résultat allouée dans la portée de la fonction multiplyMatrix doit également être désallouée explicitement.

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

Article connexe - C++ Math