2012-03-24 4 views
1

Ceci est ma première publication, donc je vais m'excuser pour mes erreurs de débutant. Veuillez également excuser le fait que tous les noms de variables ne sont pas en anglais. Mon problème est le suivant: j'ai écrit ce code en utilisant openMP dans Visual Studio 2010 et dans eclipse pour c/C++ en utilisant le toolchain du compilateur cygwin gcc. En visuel j'obtiens une accélération mais en éclipse j'obtiens un ralentissement de deux fois le montant de la version sérielle. Quelqu'un peut-il expliquer s'il vous plaît ce que j'ai mal fait s'il vous plaît? En bref, je simule simplement l'accélération à partir de quand je copie d'un tableau de vecteurs 3D dans un double tableau afin d'envoyer sur MPI.Aide OpenMP sur le code

#include <omp.h> 
#include <time.h> 
#include <stdio.h> 
#include <vector> 
const int NUMAR_FORME=10; 
    const int NUMAR_SECUNDE_SIMULATE=60; //number of buffers 
    const int dimensiuni_forme[10]={100,200,300,400,500,600,700,800,900,10000}; //size of each buffer 
    //-------- the buffers, cuurently only worker_buffer and buff is used 
    std::vector<std::vector<std::vector<double> > > worker_buffer; 
    std::vector<std::vector<double> > send_buffer,corect; 
    double **buff; 
    double **worker_buffer1; 
    long i,j,k,l; 
int flag=0; 
int numarator=0; //number of tests runed 
clock_t start; 
start=clock(); 
worker_buffer.resize(1); 
buff = new double* [2]; 
int de_scris=0; //this tells me in which buffer to store, nou I alternate buff[0], buff[1], buff[0], buff[1] 
worker_buffer[0].resize(NUMAR_SECUNDE_SIMULATE); 
for(i=0;i<NUMAR_SECUNDE_SIMULATE;i++) 
    worker_buffer[0][i].resize(dimensiuni_forme[9]); 



while(numarator<60) 
{ 

     if(numarator!=0) 
      delete [] buff[de_scris]; 

    if(numarator!=0) 
     de_scris=(de_scris+1)%2; 
    long limita; 
    limita=NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3; //3-comes from the fact that I will have a 3D vector structure 
    buff[de_scris]= new double [limita]; 
    for(i=0;i<NUMAR_SECUNDE_SIMULATE;i++) 
    { for(j=0;j<dimensiuni_forme[9];j++) 
     { 
      worker_buffer[0][i][j]=(i*dimensiuni_forme[9]+j)*3; 
      buff[de_scris][(i*dimensiuni_forme[9]+j)*3]=worker_buffer[0][i][j]; 
      buff[de_scris][(i*dimensiuni_forme[9]+j)*3+1]=worker_buffer[0][i][j]+0.5; 
      buff[de_scris][(i*dimensiuni_forme[9]+j)*3+2]=worker_buffer[0][i][j]+0.75; 
     } 
    } 
    numarator++; 

} 

start=clock()-start; 
printf("TICKS TOTAL %ld \n",start); 
bool ad=true; 
long nr; 
for(i=0;i<NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3;i++) 
{ 
    if(i%3==0) 
     nr=i; 
    if(i%3==0 && buff[de_scris][i]!=i) 
     ad=false; 
    else 
     if(i%3==1 &&buff[de_scris][i]!=(nr+0.5)) 
      ad=false; 
     else 
      if(i%3==2 && buff[de_scris][i]!=(nr+0.75)) 
       ad=false; 
} 
if(ad==false) 
    printf("not correct \n"); 
start=clock(); 

    numarator=0; 
//parallel version 
while(numarator<60) 
{ 


     if(numarator!=0) 
      delete [] buff[de_scris]; 

    long index, limita,id; 
    omp_set_num_threads(2); 

    if(numarator!=0) 
     de_scris=(de_scris+1)%2; 
    limita=NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3; //3- 
    buff[de_scris]= new double [limita]; 
#pragma omp parallel shared(worker_buffer,limita,buff) private(index,id) 
    { 
     printf("intram cu %d threaduri \n", omp_get_num_threads()); 
     id=omp_get_thread_num(); 
     //index=id; 
     for(index=id;(index*3)<limita;index+=omp_get_num_threads()) 
     { 
      buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x 
      buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5; 
      buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75; 
     } 

    // index+=omp_get_num_threads(); 


    }//end parallel zone 
    numarator++; 
} 

start=clock()-start; 
printf("TICKS TOTAL %ld \n",start); 
ad=true; 
    //testing for correctness 
for(i=0;i<NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3;i++) 
{ 
    if(i%3==0) 
     nr=i; 
    if(i%3==0 && buff[de_scris][i]!=i) 
     ad=false; 
    else 
     if(i%3==1 &&buff[de_scris][i]!=(nr+0.5)) 
      ad=false; 
     else 
      if(i%3==2 && buff[de_scris][i]!=(nr+0.75)) 
       ad=false; 
} 
if(ad==false) 
    printf("not correct \n"); 
return 0; 
} 
+0

Mesurez-vous le temps que la fonction d'horloge dans votre code? Si c'est le cas, vous devez savoir que l'horloge renvoie le temps CPU utilisé, ce qui signifie que si vous utilisez 2 prossesors, le temps retourné par clock() augmentera deux fois plus vite que le temps réel. Je ne suis pas sûr à 100% si visucal C++ implémente la fonction clock() de la même manière, peut être la raison pour laquelle vous mesurez des temps différents. – Haatschii

+0

J'ai essayé d'utiliser time() et clock_gettime() le résultat était le même – Ray

Répondre

1

A en juger par la façon dont vous avez organisé cette boucle:

for(index=id;(index*3)<limita;index+=omp_get_num_threads()) 
    { 
     buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x 
     buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5; 
     buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75; 
    } 

et en supposant que vous avez 4 fils, vos fils auront des valeurs d'index intercalés:

thread 0: 0, 4, 8, 12,... 
thread 1: 1, 5, 9, 13,... 
thread 2: 2, 6, 10, 14,... 
thread 3: 3, 7, 11, 15,... 

qui peut être à l'origine Mettez en cache les effets de ping-pong, car les valeurs écrites par différents threads peuvent se retrouver sur la même ligne de cache, ralentissant ainsi votre exécution.

Essayez d'utiliser une simple boucle avec partitionnement statique au lieu, afin d'obtenir des partitions continues:

#pragma omp parallel for 
    for(index = 0; index < limita/3;index++) 
    { 
     buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x 
     buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5; 
     buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75; 
    } 
+0

Vous aviez raison, merci beaucoup, j'ai utilisé la boucle que vous avez écrite et elle a montré une accélération. Étrange comment en visuel il a montré une vitesse sans utiliser la directive for. – Ray

+0

@Ray: Content de vous aider. Ne pas oublier d'accepter la réponse si elle a résolu votre problème. – Tudor