2016-08-19 3 views
4

Я тестирую ускорения параллельной программы на C с использованием OpenMP. Используя флаг -O3 для компиляции кода с gcc, время выполнения кажется намного меньшим. Тем не менее, я постоянно получаю более медленные ускорения для разных номеров потоков (2,4,8,16,24) по сравнению с кодом, скомпилированным без флагов оптимизации. Как это возможно?Флаг оптимизации O3, делающий ускорения хуже в параллельной обработке

Подробнее о том, что я нашел до сих пор. Я пишу код для нахождения простых чисел на основе Sieve of Eratosthenes и пытаюсь оптимизировать его с помощью параллельной версии с использованием OpenMP. Вот код

#include <stdio.h> 
#include <stdlib.h> 
#include <omp.h> 
#include <math.h> 

// ind2num: returns the integer (3<=odd<=numMax) 
//  represented by index i at prime_numbers (0<=i<=maxInd) 
#define ind2num(i) (2*(i)+3) 
// num2ind: retorns the index (0<=i<=maxInd) at prime_numbers 
//  which represents the number (3<=odd<=numMax) 
#define num2ind(i) (((i)-3)/2) 

// Sieve: find all prime numbers until ind2num(maxInd) 
void Sieve(int *prime_numbers, long maxInd) { 
    long maxSqrt; 
    long baseInd; 
    long base; 
    long i; 

    // square root of the largest integer (largest possible prime factor) 
    maxSqrt = (long) sqrt((long) ind2num(maxInd)); 

    // first base 
    baseInd=0; 
    base=3; 

    do { 
     // marks as non-prime all multiples of base starting at base^2 
     #pragma omp parallel for schedule (static) 
     for (i=num2ind(base*base); i<=maxInd; i+=base) { 
      prime_numbers[i]=0; 
     } 

     // updates base to next prime number 
     for (baseInd=baseInd+1; baseInd<=maxInd; baseInd++) 
      if (primos[baseInd]) { 
       base = ind2num(baseInd); 
       break; 
      } 
    } 
    while (baseInd <= maxInd && base <= maxSqrt); 

} 

Если я исполню его, чтобы найти все простые числа меньше, чем 1000000000 (10^9), к примеру, я в конечном итоге со следующим временем выполнения для различного числа нитей (1,2, 4,8,16,24):

Без -O3 | 56.31s | 28.87s | 21.77s | 11.19s | 6.13s | 4.50s |

С -O3 .... | 10.10s | 5.23s | 3.74s | 2.81s | 2.62s | 2.52s |

Вот соответствующие скорости окна:

Без -O3 | 1 | 1.95 | 2,59 | 5,03 | 9.19 | 12.51 |

С -O3 .... | 1 | 1.93 | 2.70 | 3,59 | 3,85 | 4.01 |

Почему я продолжаю получать более низкие ускорения с флагом -O3?

+0

@ user3386109, он распараллеливает процесс вычеркивания кратных заданного штриха из сита (ищите '#pragma omp'). –

+0

Как вы вычисляете время и что представляют цифры (например, diff 'clock_gettime')? Он выглядит как (например,) для 24, без '-O3' составляет 4,5 с, а с 2,52 с (то есть с увеличением ~ 2x быстрее). Вы подтвердили, что _results_ одинаковы для всех # потоков? То есть, никакое условие гонки в модификации «primos». Кроме того, помимо ~ 4 потоков, вы можете насытить шину памяти доступом к «primos», и это ограничивающий фактор, независимо от количества ядер. –

+4

Для каждого количества потоков время выполнения оптимизированного кода «-O3» ниже, чем время выполнения оптимизированного по умолчанию кода. Вот о чем вы должны смотреть. Нет причин предполагать, что ускорение с увеличением количества строк должно быть одинаковым для одного случая, а для другого - сравнение ускорений * разных программ *. –

ответ

4

Существует определенный объем пропускной способности памяти, который потребует выполнение алгоритма. Чем меньше оптимизирован код, тем больше внутренних ошибок процессора доминируют во время выполнения. Чем больше оптимизирован код, тем больше скорости памяти превышает время выполнения.

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

+6

Я бы сказал, что в этом конкретном случае масштабируемость ограничена служебными данными OpenMP и тем фактом, что только часть кода параллельна (закон Амдаля). Компиляция без оптимизаций увеличивает параллельное время, тем самым уменьшая процентную часть служебной + последовательной части. –

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