открытый MP - точечный продукт - PullRequest
0 голосов
/ 20 марта 2011

Я реализую параллельный точечный продукт в открытом MP

У меня есть этот код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <omp.h>
#define SIZE 1000

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

  float u[SIZE], v[SIZE], dp,dpp;
  int i, j, tid;

  dp=0.0;
  for(i=0;i<SIZE;i++){
      u[i]=1.0*(i+1);
      v[i]=1.0*(i+2);
  }
  printf("\n values of u and v:\n");

  for (i=0;i<SIZE;i++){
      printf(" u[%d]= %.1f\t v[%d]= %.1f\n",i,u[i],i,v[i]);
  }
  #pragma omp parallel shared(u,v,dp,dpp) private (tid,i)
  {
      tid=omp_get_thread_num();

      #pragma omp for private (i)
      for(i=0;i<SIZE;i++){
          dpp+=u[i]*v[i];
          printf("thread: %d\n", tid);
      }
      #pragma omp critical
      {
          dp=dpp;
          printf("thread %d\n",tid);
      }


  }

  printf("\n dot product is %f\n",dp);

 }

Я начинаю его с: pgcc -B -Mconcur -Minfo -o prog prog.c

И результат Iполучить в консоли это:

33, Loop not parallelized: innermost 

39, Loop not vectorized/parallelized: contains call

48, Loop not vectorized/parallelized: contains call

Что я делаю не так?

С моей стороны все выглядит хорошо.

Ответы [ 2 ]

2 голосов
/ 20 марта 2011

Проблема все та же, что и в вашем последнем вопросе. Вы накапливаете значения в переменной, и вы должны указать OpenMp, как это сделать:

#pragma omp for reduction(+: dpp)
for(size_t i=0; i<SIZE; i++){
  dpp += u[i]*v[i];
}

Используйте локальную переменную цикла для индекса, и это все, что вам нужно, забудьте обо всем, что вы делаете для этого. Если вы хотите увидеть, что компилятор делает с вашим кодом, запустите его с -S и проверьте вывод ассемблера. Это может быть очень поучительно, потому что тогда вы узнаете, каковы простые простые выражения, когда они распараллеливаются.

И не используйте int для индексов цикла. Размеры и тому подобное size_t.

2 голосов
/ 20 марта 2011

Прежде всего, простой точечный продукт из 1000 элементов не обладает достаточными вычислительными затратами для оправдания многопоточности - вы заплатите гораздо больше затрат на связь и синхронизацию, чем вы получите в производительности, что оно не стоит это.

Во-вторых, похоже, что вы вычисляете произведение полной точки в каждом потоке, не разделяя вычисления на несколько потоков и объединяя результат в конце.

Вот пример того, как сделать продукты векторной точки из https://computing.llnl.gov/tutorials/openMP/#SHARED

#include <omp.h>

main ()
{
  int   i, n, chunk;
  float a[100], b[100], result;

  /* Some initializations */
  n = 100;
  chunk = 10;
  result = 0.0;
  for (i=0; i < n; i++) {
      a[i] = i * 1.0;
      b[i] = i * 2.0;
  }

  #pragma omp parallel for      \  
      default(shared) private(i)  \  
      schedule(static,chunk)      \  
      reduction(+:result)  

    for (i=0; i < n; i++)
        result += (a[i] * b[i]);

  printf("Final result= %f\n",result);
}

По сути, OpenMP хорош для выполнения грубого параллелизма, когда у вас большие, дорогие циклы. В общем, когда вы выполняете параллельное программирование, чем больше «кусков» вычислений вы можете сделать перед повторной синхронизацией, тем лучше. Тем более, что количество ядер увеличивается, расходы на связь и синхронизацию будут расти. Представьте, что каждая синхронизация (получение нового индекса или части индексов для выполнения, вход в критический раздел и т. Д.) Обходится вам в 10 мс или 1 МБ инструкций, чтобы получить лучшее представление о том, когда / где / как распараллеливать ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...