Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Общие вопросы > Распараллеливание с помощью openmp


Автор: shonny 14.11.17, 16:57
Здравствуйте, вообщем пытаюсь использовать Openmp, чтобы распараллелить задачу вычисления экспоненты с помощью ряда Тейлора. Программа работает, но при сравнении времени выполнения последовательного кода и с Openmp, нет прироста скорости, а даже наоборот выполняется дольше с Openmp. В чем может быть причина, не могли бы вы помочь?
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <omp.h>
    int fact(int c);
    double taylor(double x, int n);
     
    int main(int argc, char *argv[]) {
      double x=0;
      int n=0;
      int n_max = 32;
      if (argc != 3) {
      printf("Input three parametrs!\n");
      return 1;
    }
      sscanf(argv[1], "%lf", &x);
      sscanf(argv[2], "%d", &n);
     
     if((n>n_max)||(n<0)) {
     printf("Invalid parameter n, enter n from 0..10\n");
     return 1;
     }
        
     int i;
     double sum=0 ;
     double t = omp_get_wtime();
     
      #pragma omp parallel for private(i) reduction(+: sum)
       for (i=1; i<=n; i++) {
          double taylor = pow(x,i)/fact(i);
          sum+=taylor;
      }
      
      double diff = omp_get_wtime() - t;
      printf("e^x = %lf\n Time: \t %lf\n", ++sum, diff);
      return 0;
    }
     
    int fact(int c) {
       int fact=1;
       int i;
       for (i = 1; i <= c; i++ ) {
          fact *=i;
       }
       return fact;
    }

./taylor 1 32
e^x = 2.718282
Time: 0.000126 - время выполнения с openmp

/staylor 1 32
e^x = 2.718282
Time: 0.000020 - время выполнения последовательного кода

Автор: Qraizer 14.11.17, 17:17
Накладные на создание потоков велики. На 32-ух итерациях они не окупятся.

Автор: Славян 14.11.17, 17:23
Слишком крохотные времена для функций. Попробуйте искусственно удлинить fact(), чтобы проверить действие распараллеливания. Можно прибавлять 2, а вычитать длиннющий ряд 1 + 1/2 + 1/4 + ... или что-то ещё такое.

Автор: Qraizer 14.11.17, 18:20
Топорнейшим образом переписал вот так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
     double t;
     #pragma omp parallel private(i) reduction(+: sum)
     {
       for (i=1; i<=n; i++) {
          double taylor = pow(x,i)/fact(i);
          sum+=taylor;
      }
     sum = 0;
     t = omp_get_wtime();
       for (i=1; i<=n; i++) {
          double taylor = pow(x,i)/fact(i);
          sum+=taylor;
      }
     }
чтобы время создания не учитывалось, получил:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    e^x = 7.873127
     Time:   0.000012
    ...
    e^x = 7.873127
     Time:   0.000005
Но всё равно, 32 итерации – это крайне мало для накопления статистики. На отклонение будут влиять малейшие чихи ОС, включая асинхронные прерывания от сетевухи.

Автор: Славян 14.11.17, 19:12
Qraizer, так всё ж "наоборот"! Не в 32 итерациях суть, а в мощности каждой из них. Если их хоть 8, или 3, и каждая будет работать по часу, то и выигрыш будет в разы! А если их хоть миллион, но каждая длится миллисекунды, то перещёлкивание потоков всё (выигрыш) и съест. Или как?.. :whistle:

Автор: Qraizer 14.11.17, 20:15
Можно и так сказать. Только алгоритм на секунды не перепишешь, а итераций можно добавить.

Автор: _lcf_ 14.11.17, 20:26
если хочется выжать максимум из железа, то использование опенмп - плохая затея. только ручками и только с глубоким пониманием сабжа. на малых затратах итерации делить на потоки - организация потока, кэш, ух.... :facepalm: а с опенмп еще надо постоянно анализировать потоки в потоках :)

Автор: JoeUser 15.11.17, 03:28
Цитата _lcf_ @
если хочется выжать максимум из железа, то использование опенмп - плохая затея. только ручками и только с глубоким пониманием сабжа. на малых затратах итерации делить на потоки - организация потока, кэш, ух.... :facepalm: а с опенмп еще надо постоянно анализировать потоки в потоках :)

В каждом предложении не хватает завершения мысли в виде "потому что ..."

Автор: _lcf_ 15.11.17, 08:03
а что там завершать? опенмп топорнейший инструмент, который тупо делит указанные части кода на потоки, нисколько не анализируя и не оптимизируя затраченное время и нагрузку процов. банальное гетнампроц и крэйттрид делает по сути то же самое :-? я бы сказал это инструмент для начинающих/ленивых :)

Автор: JoeUser 15.11.17, 13:02
Цитата _lcf_ @
нисколько не анализируя и не оптимизируя затраченное время и нагрузку процов

А смысл у операционной системы забирать ее функции? Планирование загрузки процов - это же прерогатива ОС, не? Конечно можно насильно вязать нити к ядрам, но что это даст в профите? Я понимаю, если в пуле создаваемых нитей нагрузка (по времени) распределена неравномерно, тогда да. А если равномерно?

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)