Помощь OpenMP по коду - PullRequest
       12

Помощь OpenMP по коду

1 голос
/ 24 марта 2012

это мой первый пост, поэтому я буду извиняться за ошибки новичка.Пожалуйста, извините, что не все имена переменных написаны на английском языке.Моя проблема заключается в следующем: я написал этот код с использованием openMP как в Visual Studio 2010, так и в eclipse для c / c ++, используя набор инструментов компилятора gg cygwin.В визуализации я получаю ускорение, но в затмении я получаю замедление вдвое больше, чем в серийной версии.Может кто-нибудь объяснить, пожалуйста, что я сделал не так, пожалуйста?Короче говоря, я просто имитирую ускорение, когда копирую из массива трехмерных векторов в двойной массив для отправки через MPI.

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

1 Ответ

1 голос
/ 25 марта 2012

Судя по тому, как вы организовали это для цикла:

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

и при условии, что у вас 4 потока, ваши потоки получат чередующиеся значения индекса:

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

, что может вызывать эффекты кеш-пинг-понга, поскольку значения, записанные разными потоками, могут попадать в одну и ту же строку кэша, что замедляет выполнение.

Попробуйте вместо этого использовать простой цикл for со статическим разбиением, чтобы получить непрерывные разбиения:

    #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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...