Problema con i threads

di il
4 risposte

Problema con i threads

Ciao ragazzi,
sono sempre io che tento di parallelizzare utilizzando openmp!
Sto provando a parallelizzare una semplice moltiplicazione fra 2 matrici riempite di '1'... Tutto ok nell'esecuzione del programma se non che ho un problemino con il numero dei threads all'interno della parallelizzazione. Quando chiedo ad ogni thread di dirmi il proprio numero mi viene fuori che un thread è doppio o triplo e non riesco a capire il perchè!!!!
Vi posto il codice (spero sia chiaro):

#include <stdio.h>
#include <omp.h>
#include <stdlib.h>

int main(int argc, char **argv)
{

                                            //Dichiarazione delle variabili, delle dimensioni

int i,j,k,nt=4,m=5,h=5,n=5;                 //delle matrici e del numero di threads (nt)
int num,esimo,procs;                

double tempotot,start,end; 
unsigned int result=0;                      //variabile d'appoggio

    
//Allocazione dinamica delle due matrici da moltiplicare e della matrice risultato C

int* A=(int*)calloc(m*h,sizeof(int*));
int* B=(int*)calloc(h*n,sizeof(int*));
int* C=(int*)calloc(m*n,sizeof(int*));

    
for(i=0;i<m;i++)                            //Riempimento della matrice A
      for(j=0;j<h;j++)
        A[j+i*h]=1;                         //Utilizzeremo una matrice costituita da tutti 1


for(i=0;i<h;i++)                            //Riempimento della matrice B
      for(j=0;j<n;j++)
        B[j+i*n]=1;                         //Utilizzeremo una matrice costituita da tutti 1



printf("Stampo le matrici A e B: \n");
  for(i=0;i<m;i++){                        //Stampa delle matrici
      for(j=0;j<h;j++){
        printf("%d ",A[j+i*h]);
        }
        printf("\n");
        }
        printf("\n");

    for(i=0;i<h;i++){
      for(j=0;j<n;j++){
        printf("%d ",B[j+i*n]);
        }
        printf("\n");
        }
      
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Controllo core e threads @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
                             num = omp_get_num_threads();                 
                             esimo = omp_get_thread_num();

                             procs = omp_get_num_procs();
                             printf("\nSono disponibili %d core.\n",procs);


                             printf("Fuori dalla zona parallela ci sono %d thread e questo è il thread num %d.\n\n",num,esimo);

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      

                                            //Inizio calcolo dei tempi
    start=omp_get_wtime();
                                            //Inizio parte parallela:


#pragma omp parallel for schedule(dynamic) num_threads(nt) shared(m,n,h,A,B,C) private(j,k,result)
                             
for(i=0;i<m;i++){

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Controllo dentro alla parte parallelizzata @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

                             num = omp_get_num_threads();                 
                             esimo = omp_get_thread_num();
                             printf("Qui (dentro al for #pragma) ci sono %d threads, io sono il numero %d\n",num,esimo);

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


       for(j=0;j<n;j++){
       result=0;                            //Resetto la variabile d'appoggio
       for(k=0;k<h;k++)
       result=result+A[k+i*h]*B[j+k*n];
      C[j+i*n]=result;          //l'uso di questa variabile permette di evitare il problema del false sharing
          }
          }
    end=omp_get_wtime();                    //Fine calcolo dei tempi
    tempotot=end-start;


//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Fuori dalla parallelizzazione @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                             
                             num = omp_get_num_threads();                 
                             esimo = omp_get_thread_num();
                             printf("\nQui (fine #pragma) ci sono %d threads, io sono il numero %d.\n",num,esimo);


//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   

printf("\nRisultato della moltiplicazione:\n");                               //Stampa finale del risultato

    for(i=0;i<m;i++){
         for(j=0;j<n;j++){
           printf("%d ",C[j+i*n]);
         }
printf("\n");  
    }      
printf("\nTempo totale : %f secondi.\n",tempotot); 
    

// Esecuzione del programma in modo sequenziale

printf("\nEsegue il codice in modo sequenziale: ");
start=omp_get_wtime();

for(i=0;i<m;i++){
for(j=0;j<n;j++){

       result=0;                            
       for(k=0;k<h;k++)
       result=result+A[k+i*h]*B[j+k*n];
          C[j+i*n]=result;          
          }
          }
end=omp_get_wtime();
tempotot=end-start;
printf("tempo totale : %f secondi.\n",tempotot);



free(A);                                    //Deallocazione delle matrici
free(B);
free(C);
}
Infine vi chiedo anche se sapete spiegarmi perchè eseguendo il programma in modo sequenziale ci mette meno tempo rispetto all'esecuzione in parallelo...
Vi posto anche l'output:

[xPecax@localhost ~]$ ./a.out
Stampo le matrici A e B: 
1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 

1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 

Sono disponibili 4 core.
Fuori dalla zona parallela ci sono 1 thread e questo è il thread num 0.

Qui (dentro al for #pragma) ci sono 4 threads, io sono il numero 3
Qui (dentro al for #pragma) ci sono 4 threads, io sono il numero 3
Qui (dentro al for #pragma) ci sono 4 threads, io sono il numero 3
Qui (dentro al for #pragma) ci sono 4 threads, io sono il numero 2
Qui (dentro al for #pragma) ci sono 4 threads, io sono il numero 1

Qui (fine #pragma) ci sono 1 threads, io sono il numero 0.

Risultato della moltiplicazione:
5 5 5 5 5 
5 5 5 5 5 
5 5 5 5 5 
5 5 5 5 5 
5 5 5 5 5 

Tempo totale : 0.017916 secondi.

Esegue il codice in modo sequenziale: tempo totale : 0.000002 secondi.
[xPecax@localhost ~]$ 
In questo caso ho il thread numero 3 che mi esce 3 volte!!!!

4 Risposte

  • Re: Problema con i threads

    Ragazzi per la prima domanda mi sono auto risposto da solo: giustamente sono dentro a un for che gira 5 volte e ho 4 threads... per cui qualcuno dovrà ripetere il for... giusto?
  • Re: Problema con i threads

    Peca ha scritto:


    Infine vi chiedo anche se sapete spiegarmi perchè eseguendo il programma in modo sequenziale ci mette meno tempo rispetto all'esecuzione in parallelo...
    I problema potrebbe dipendere dal fatto che i due thread lavorano sulla stessa area di memoria. Nell' hardware hai piu core ma un solo bus di memoria quindi i due thread devono sincronizzarsi e si crea un collo di bottiglia. Inoltre l' elaborazione che fanno dei dati è brevissima (qualche moltiplicazione) quindi i tempi di accesso alla memoria sono proponderanti rispetto al resto.
  • Re: Problema con i threads

    Senza contare la printf(), che al suo interno ha un mutex che impedisce la race condition dell'output su console e che spesso è il vero collo di bottiglia.
  • Re: Problema con i threads

    barba59 ha scritto:


    I problema potrebbe dipendere dal fatto che i due thread lavorano sulla stessa area di memoria. Nell' hardware hai piu core ma un solo bus di memoria quindi i due thread devono sincronizzarsi e si crea un collo di bottiglia. Inoltre l' elaborazione che fanno dei dati è brevissima (qualche moltiplicazione) quindi i tempi di accesso alla memoria sono proponderanti rispetto al resto.
    Era quello a cui più o meno pensavo anche io riguardo alla breve elaborazione dati...
    Grazie anche per le delucidazioni del bus e del "collo di bottiglie"
Devi accedere o registrarti per scrivere nel forum
4 risposte