2012-08-27 3 views
4

Я хотел бы распараллелить эту функцию, но я новичок с открытыми мками, и я был бы признателен, если кто-то может помочь мне:OpenMP C++ - Как распараллелить эту функцию?

void my_function(float** A,int nbNeurons,int nbOutput, float* p, float* amp){ 
    float t=0; 
    for(int r=0;r<nbNeurons;r++){ 
     t+=p[r]; 
    } 

    for(int i=0;i<nbOutput;i++){ 
     float coef=0; 
     for(int r=0;r<nbNeurons;r++){ 
     coef+=p[r]*A[r][i]; 
     } 
    amp[i]=coef/t; 
    } 
} 

Я не знаю, как распараллелить это правильно, так как из двойная петля для, на данный момент, я только подумал о том, чтобы сделать: #pragma omp parallel for reduction(+:t)

Но я думаю, что это не лучший способ быстрее получить вычисления через openMp.

Спасибо заранее,

+0

Не позволяйте двойной петле вас пугать. Вы также можете использовать OpenMP 'прагма'. – Mysticial

+1

Параллельный внешний контур. –

ответ

8

Прежде всего: мы должны знать контекст. Где ваш профилировщик говорит вам, сколько времени потрачено?

В целом, крупнозернистая параллелистика работает лучше всего, так как @Alex сказал: parallellize внешний для петли.

void my_function(float** A,int nbNeurons,int nbOutput, float* p, float* amp) 
{ 
    float t=0; 
    for(int r=0;r<nbNeurons;r++) 
     t+=p[r]; 

#pragma parallel omp for 
    for(int i=0;i<nbOutput;i++){ 
     float coef=0; 
     for(int r=0;r<nbNeurons;r++){ 
      coef+=p[r]*A[r][i]; 
     } 
     amp[i]=coef/t; 
    } 
} 

В зависимости от фактических объемов, это может быть интересно вычислить т в фоновом режиме, и переместить разделение из параллельного цикла:

void my_function(float** A,int nbNeurons,int nbOutput, float* p, float* amp) 
{ 
    float t=0; 
#pragma omp parallel shared(amp) 
    { 
#pragma omp single nowait // only a single thread executes this 
     { 
      for(int r=0;r<nbNeurons;r++) 
       t+=p[r]; 
     } 

#pragma omp for 
     for(int i=0;i<nbOutput;i++){ 
      float coef=0; 
      for(int r=0;r<nbNeurons;r++){ 
       coef+=p[r]*A[r][i]; 
      } 
      amp[i]=coef; 
     } 

#pragma omp barrier 
#pragma omp master // only a single thread executes this 
     { 
      for(int i=0; i<nbOutput; i++){ 
       amp[i] /= t; 
      } 
     } 
    } 
} 

Примечания непроверенного кода. Иногда OMP имеет сложную семантику, поэтому я, возможно, пропустил там «общую» декларацию. Тем не менее, профайлер не будет уведомлять вас об этом быстро.

+0

Большое спасибо за ваши ответы, это нормально, если parellelize более высокий цикл, даже если я изменяю значение внутри? Я имею в виду, что это + = и не простая привязанность =. Благодарю. Parellelization настолько сложна ... – kuider

+0

В эксклюзивных разделах есть только + = и/=. Коф не делится нитями – sehe

+1

Я бы EITHER {добавьте «nowait» в конце одной прагмы omp и «#pragma барьер» в самом конце функции. } ИЛИ { no "nowait", но верните "/ t" обратно в цикл parrellelized for. } –

Смежные вопросы