openmp поделился или ничего.личное против неинициализированного - PullRequest
0 голосов
/ 23 февраля 2019

Есть ли разница между этими двумя реализациями openmp?

float dot_prod (float* a, float* b, int N)
{
float sum = 0.0;
#pragma omp parallel for shared(sum)
for (int i = 0; i < N; i++) {
  #pragma omp critical
  sum += a[i] * b[i];
  }
return sum;
}

и тем же кодом, но строка 4 не имеет общего (sum), потому что sum уже инициализирована?

#pragma omp parallel for
for(int = 0; ....)

Тот же вопрос для частного в openmp:

Является ли

void work(float* c, int N)
{
float x, y; int i;
#pragma omp parallel for private(x,y)
for (i = 0; i < N; i++)
{
  x = a[i]; y = b[i];
  c[i] = x + y;
  }
}

таким же, как и без частного (x, y), потому что x и y не инициализированы?

#pragma omp parallel for 

1 Ответ

0 голосов
/ 23 февраля 2019

Есть ли разница между этими двумя реализациями openmp?

float dot_prod (float* a, float* b, int N)
{
  float sum = 0.0;
# pragma omp parallel for shared(sum)
  for (int i = 0; i < N; i++) {
    #pragma omp critical
    sum += a[i] * b[i];
  }
  return sum;
}

В openMP переменная, объявленная вне параллельной области видимости, равна shared, если она явно не отображается private.Следовательно, объявление shared можно опустить.

Но ваш код далеко не оптимален.Это работает, но будет намного медленнее, чем его последовательный аналог, потому что critical вызовет последовательную обработку, а создание критического раздела требует значительных временных затрат.

В правильной реализации будет использоваться reduction.

float dot_prod (float* a, float* b, int N)
{
  float sum = 0.0;
# pragma omp parallel for reduction(+:sum)
  for (int i = 0; i < N; i++) {
    sum += a[i] * b[i];
  }
  return sum;
}

Сокращение создает скрытую локальную переменную, которая параллельно накапливается в каждом потоке, и перед уничтожением потока выполняет атомарное добавление этих локальных сумм к общей переменной sum.

Тот же вопрос для частного в openmp:

void work(float* c, int N)
{
  float x, y; int i;
# pragma omp parallel for private(x,y)
  for (i = 0; i < N; i++)
  {
    x = a[i]; y = b[i];
    c[i] = x + y;
  }
}

По умолчанию, x и y являются общими.Таким образом, без private поведение будет другим (и глючит, потому что все потоки будут изменять одни и те же глобально доступные переменные x и y без атомарного доступа).

так же, как и безprivate (x, y), потому что x и y не инициализированы?

Инициализация x и y не имеет значения, важно то, где они объявлены.Чтобы обеспечить правильное поведение, они должны быть сделаны частными, и код будет правильным, так как x и y установлены перед использованием в цикле.

...