Help mesure des performances de la parallelis

shanez -  
mamiemando Messages postés 34188 Statut Modérateur -
Bonjour,
je suis étudiante en 3eme informatique et j'ai comme thème mesure des performances de la parallélisation en mémoire partagée je travail donc sur le produit de deux matrices avec la bibliothèque open mp sous linux enfin ubunto mais j'avoue etre vraiment perdue pour le programme
j'ai besoin d'aide alors si quelqu'un peut m'aider !!!!!!!!!!



A voir également:

1 réponse

mamiemando Messages postés 34188 Statut Modérateur 7 890
 
Je pense que le point de départ c'est cherché un tutoriel basique, tenter de le reproduire, et ensuite de le corriger petit à petit pour atteindre ton objectif. Tu peux par exemple partir de ceci :
https://www.azote.org/disabled.html

Dans le cas d'un produit matriciel A * B = C, le calcul de chaque terme de C est indépendant, donc on peut calculer en parallèle tous les coefficients de C :
https://www.azote.org/disabled.html

Il faut donc commencer par définir une classe dans lesquelles stocker tes matrices. Par exemple si tu codes en C++ tu peux par exemple écrire un truc du genre :

Voici à quoi ressemblerait par exemple le code d'une matrice générique en C++ (ici je n'ai codé que ce qui permet de créer la matrice, d'accéder à ses éléments a[i][j] (opérateurs []), de calculer le produit de deux matrices (opérateur *), et de l'afficher (opérateur <<).

matrix.hpp
#ifndef MATRIX_HPP 
#define MATRIX_HPP 

#include <vector> 
#include <ostream> 

template <typename T> 
class matrix_t { 
  private: 
    std::size_t n_rows; 
    std::size_t n_cols; 
    std::vector<std::vector<T> > values; 
  public: 
    matrix_t(){} 

    matrix_t( 
      std::size_t n_rows0, 
      std::size_t n_cols0 
    ): 
      n_rows(n_rows0), 
      n_cols(n_cols0) 
    { 
      this->values = std::vector<std::vector<T> >(
        n_rows,
        std::vector<T>(n_cols)
      ); 
    } 

    inline std::size_t num_rows() const { 
      return this->n_rows; 
    } 

    inline std::size_t num_cols() const { 
      return this->n_cols; 
    } 

    // Accès à une ligne (lecture) 
    inline const std::vector<T> & operator[](std::size_t & row) const { 
      return this->values[row]; 
    } 

    // Accès à une ligne écriture (lecture) 
    inline std::vector<T> & operator[](std::size_t & row){ 
      return this->values[row]; 
    } 
}; 

// Multiplication 
template <typename T> 
matrix_t<T> operator * ( 
  const matrix_t<T> & a, 
  const matrix_t<T> & b  
) { 
  if(a.num_cols() != b.num_rows()) throw; 
  matrix_t<T> c = matrix_t<T>(
    a.num_rows(),
    b.num_cols()
  ); 
  for(std::size_t i = 0; i < a.num_rows(); i++) { 
    for(std::size_t j = 0; j < a.num_cols(); j++) { 
      for(std::size_t k = 0; k < b.num_cols(); k++) { 
        c[i][k] = a[i][j] * b[j][k]; 
      } 
    } 
  } 
  return c; 
} 

// Affichage 
template <typename T> 
std::ostream & operator << (
  std::ostream & out,
  const matrix_t<T> matrix
) { 
  for(std::size_t i = 0; i < matrix.num_rows(); i++) { 
    for(std::size_t j = 0; j < matrix.num_cols(); j++) { 
      out << matrix[i][j] << '\t'; 
    } 
    out << std::endl; 
  } 
  return out; 
} 

#endif 


main.cpp

#include <iostream> 
#include "matrix.hpp"  

int main(){ 
  matrix_t<int> a(5, 3); 
  matrix_t<int> b(3, 4); 
   
  for(std::size_t i = 0; i < a.num_rows(); i++) { 
    for(std::size_t j = 0; j < a.num_cols(); j++) { 
      a[i][j] = i + 10*j; 
    } 
  } 

  for(std::size_t i = 0; i < b.num_rows(); i++) { 
    for(std::size_t j = 0; j < b.num_cols(); j++) { 
      b[i][j] = 10*i + 100*j; 
    } 
  } 

  matrix_t<int> c = a * b; 
  std::cout << "a = " << std::endl << a << std::endl 
            << "b = " << std::endl << b << std::endl 
            << "c = " << std::endl << c << std::endl; 
  return 0; 
} 


Ensuite on compile :

g++ -W -Wall main.cpp -o matrice


... et on exécute :

./matrice


Ce qui donne :

a =  
0       10      20 
1       11      21 
2       12      22 
3       13      23 
4       14      24 

b =  
0       100     200     300 
10      110     210     310 
20      120     220     320 

c =  
400     2400    4400    6400 
420     2520    4620    6720 
440     2640    4840    7040 
460     2760    5060    7360 
480     2880    5280    7680


Ok c'est cool maintenant, revenons à openmp. Dans notre cas c'est la multiplication qui nous préoccupe. Tu noteras que << ne serait pas parallélisable car chaque coefficient de la matrice doit être écrit "dans l'ordre" (de haut en bas et de gauche à droite). Dans le cas du produit matriciel, peut importe l'ordre dans lequel les coefficients de C sont calculés. On s'intéresse donc à cette partie du code :

  ... 
  for(std::size_t i = 0; i < a.num_rows(); i++) { 
    for(std::size_t j = 0; j < a.num_cols(); j++) { 
      for(std::size_t k = 0; k < b.num_cols(); k++) { 
        c[i][k] = a[i][j] * b[j][k]; 
      } 
    } 
  } 
  ...


Comme tu le vois ici les trois boucles imbriquées induisent un calcul successif de chaque terme (ce qui signifie qu'on va d'abord calculer c[0][0], puis c[0][1], puis etc... ce qui est dommage car leur calcul est indépendant. C'est là qu'openmp va nous sortir d'affaire. Je n'ai jamais utilisé cette librairie, mais toujours d'après ce lien :
https://www.azote.org/disabled.html

... il suffirait de rajouter #pragma omp parallel for devant chaque boucle for. En enlevant rajoutant ce #pragma, tu verras bien si tu le calcul est correct, mais dans l'idée je pense que le code deviendrait un truc du genre :

  ... 
  #pragma omp parallel 
  for(std::size_t i = 0; i < a.num_rows(); i++) { 
    #pragma omp parallel 
    for(std::size_t j = 0; j < a.num_cols(); j++) { 
      #pragma omp parallel 
      for(std::size_t k = 0; k < b.num_cols(); k++) { 
        c[i][k] = a[i][j] * b[j][k]; 
      } 
    } 
  } 
  ...


Bonne chance
0