2017-08-14 4 views
0

Je suis un nouveau programmeur OpenMp et maintenant j'ai un problème avec la multiplication de deux matrices. C'est mon code parallèle mais ce n'est pas aussi rapide que prévu. Par exemple, je donne un 3000 * 3000 matrice et 3000 * 3000 et mon domaine est 2 (le nombre aléatoire est 0 ou 1) et parallèle est plus lente que séquentiellematrice de multiplication parallèle openmp est plus lente que séquentielle

clock_t tStart = clock(); 
    cout<<(char)169<<" parallel "<<(char)170<<endl; 
    int a,b,c,Domain ; 
    cin>>a>>b>>c>>Domain; 
    srand(time(0)); 
    int **arr1; 
    int **arr2; 
    int **arrRet; 

    arr1 = new int*[a]; 
    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<a ; i++) 
    arr1[i] = new int [b]; 

    arr2 = new int*[b]; 
    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<b ; i++) 
    arr2[i] = new int [c]; 

    arrRet = new int*[a]; 
    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<a ; i++) 
    arrRet[i] = new int [c]; 

    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<a ; i++) 
    { 
     #pragma omp for schedule (dynamic) 
     for(int j=0; j<b ; j++) 
     { 
     arr1[i][j]=rand()%Domain; 
     } 
    } 

    //cout<<"\n\n\n"; 
    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<b ; i++) 
    { 
     #pragma omp for schedule (dynamic) 
     for(int j=0 ; j<c ; j++) 
     { 
     arr2[i][j]=rand()%Domain; 
     } 
    } 

    //cout<<"\n\n\n"; 
    #pragma omp for schedule (dynamic) 
    for(int i=0 ; i<a ; i++) 
     #pragma omp for schedule (dynamic) 
     for(int j2=0 ; j2<c ; j2++) 
     { 
      int sum=0; 
      #pragma omp parallel for shared(sum) reduction(+:sum) 
      for(int j=0 ; j<b ; j++) 
      { 
       sum+=arr1[i][j]*arr2[j][j2]; 
      } 
      arrRet[i][j2]=sum; 
     } 
    printf("Time taken : %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 
+1

double possible de [le temps et l'horloge OpenMP() calcule deux résultats différents] (https://stackoverflow.com/questions/10673732/openmp-time-and-clock-calculates-two-different-results) et https://stackoverflow.com/q/10624755/620382 – Zulan

+1

Ne faites pas de multiplication matricielle vous-même. C'est dingue. La multiplication matricielle est le problème le plus ancien du livre. Obtenez une bibliothèque pour le faire pour vous, comme OpenBLAS. Utilisez également [Armadillo] (http://arma.sourceforge.net/) pour tenir vos matrices. Arrêtez de réserver ces tableaux boiteux pour conserver des matrices. Ils sont lents parce que votre compilateur ne peut pas les vectoriser (https://fr.wikipedia.org/wiki/Automatic_vectorization). Vous pouvez lier Armadillo avec OpenBLAS et il fera la parallélisation pour vous et vos caractéristiques de processeur pour vous donner les meilleures performances. –

+0

@TheQuantumPhysicist Mon professeur me dit que je ne peux pas utiliser la bibliothèque :( – ali

Répondre

0

Il y a beaucoup optimisé très linear algebra libraries qui sont gratuit à utiliser. Je vous suggère fortement d'en utiliser un dans la mesure du possible.

Votre dégradation des performances peut être due à de nombreuses raisons. La liste suivante détaille quelques-unes des causes les plus fréquentes:

  • Utilisation de schedule(dynamic) lorsque la quantité de travail par itération est complètement équilibrée. L'omission de la clause définira la planification sur static, ce qui est plus approprié pour ce type de parallélisation.

  • Pression excessive sur l'allocation de mémoire. Vous n'avez pas réellement besoin de réserver plusieurs régions de mémoire pour une seule matrice. Puisque la taille de la matrice ne change pas dans votre programme, vous pouvez parfaitement utiliser une seule allocation pour chaque matrice. Cela améliore également la localisation des données, car les lignes contiguës sont proches les unes des autres en mémoire. Ensuite, vous pouvez accéder à chaque élément en utilisant A[ i * b + j ], où b est le nombre de colonnes.

int *A = (int *) malloc(a * b * sizeof(int)); 
  • Dans votre code, vous semblez avoir manqué une région parallel. Cela provoque que tous les omp for à l'exception de la dernière, ne sont pas exécutées par plusieurs threads.

  • fusionner vos omp for constructions dans les boucles imbriquées en utilisant collapse(2) comme dans l'exemple suivant:

#pragma omp for collapse(2) 
for(i = 0; i < a; i++) { 
    for(j = 0; j < b; j++) { 
     // your parallel code 
    } 
}