Почему версия OpenMP медленнее? - PullRequest
11 голосов
/ 28 июня 2011

Я экспериментирую с OpenMP.Я написал некоторый код, чтобы проверить его производительность.На 4-ядерном одноядерном процессоре Intel с Kubuntu 11.04 следующая программа, скомпилированная с OpenMP, примерно в 20 раз медленнее, чем программа, скомпилированная без OpenMP.Почему?

Я скомпилировал его с помощью g ++ -g -O2 -funroll-loops -fomit-frame-pointer -march = native -fopenmp

#include <math.h>
#include <iostream>

using namespace std;

int main ()
{
  long double i=0;
  long double k=0.7;

  #pragma omp parallel for reduction(+:i)
  for(int t=1; t<300000000; t++){       
    for(int n=1; n<16; n++){
      i=i+pow(k,n);
    }
  }

  cout << i<<"\t";
  return 0;
}

Ответы [ 3 ]

15 голосов
/ 28 июня 2011

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

#include <math.h>
#include <iostream>

using namespace std;

int main ()
{
  long double i=0;

#pragma omp parallel for reduction(+:i)
  for(int t=1; t<30000000; t++){       
    long double k=0.7;
    for(int n=1; n<16; n++){
      i=i+pow(k,n);
    }
  }

  cout << i<<"\t";
  return 0;
}

Следуя подсказке Мартина Беккета в комментарии ниже, вместо объявления k внутри цикла, вы также можете объявить k const и вне цикла.

В противном случае, ejd верен - проблема здесь не в плохом распараллеливании, а в плохой оптимизации при распараллеливании кода.Помните, что реализация OpenMP для gcc довольно молода и далека от оптимальной.

3 голосов
/ 11 декабря 2013

Самый быстрый код:

for (int i = 0; i < 100000000; i ++) {;}

Чуть медленнее код:

#pragma omp parallel for num_threads(1)
for (int i = 0; i < 100000000; i ++) {;}

в 2-3 раза медленнее код:

#pragma omp parallel for
for (int i = 0; i < 100000000; i ++) {;}

независимо от того, что находится между {и}. Просто ; или более сложное вычисление, те же результаты. Я скомпилировал под Ubuntu 13.10 64-bit, используя gcc и g ++, пробуя разные параметры -ansi -pedantic-errors -Wall -Wextra -O3 и работая на четырехъядерном процессоре Intel с частотой 3,5 ГГц.

Я полагаю, виноваты издержки управления потоками? Для OMP не кажется разумным создавать поток каждый раз, когда он вам нужен, и уничтожать его после. Я думал, что будет четыре (или восемь) потоков, которые либо будут работать, когда это необходимо, либо спят.

0 голосов
/ 02 апреля 2016

Я наблюдаю подобное поведение в GCC.Однако мне интересно, если в моем случае это как-то связано с шаблоном или встроенной функцией.Ваш код также находится внутри шаблона или встроенной функции?Пожалуйста, посмотрите здесь .

Однако для очень коротких циклов вы можете наблюдать небольшие издержки, связанные с переключением потоков, как в вашем случае:

#pragma omp parallel for
for (int i = 0; i < 100000000; i ++) {;}

Если ваш циклвыполняется в течение некоторого серьезного времени, всего несколько мс или даже секунд, вы должны наблюдать повышение производительности при использовании OpenMP.Но только когда у вас более одного процессора.Чем больше у вас ядер, тем выше производительность, которую вы достигаете с OpenMP.

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