Здравствуйте пишу простой алгоритм численного метода (прямоугольника). Распараллелил эту функцию с помощью OpenMP. Но время выполнения параллельного алгоритма больше, чем выполнение с одним поток. В чем ошибка? Использую пк с 12 ядрами процессора,999999999 итераций.
const unsigned long numSteps=999999999; /* default # of rectangles */
const double PI25DT = 3.141592653589793238462643;
double function(double x) //Подынтегральная функция
{
return 4.0/(1.+ x*x); //Например, sin(x)
}
double CalcIntegralWithParallel(int countThread) {
double x, pi = 0;
double sum=0.0;
double step = 1./static_cast<double>(numSteps);
#pragma omp parallel for num_threads(countThread) reduction(+:sum)
for (int i=0; i<numSteps; i++)
{
x = (i + .5)*step;
sum = sum + function(x);
}
pi = sum*step;
return pi;
}
double CalcIntegral(double a, double b) {
double x, pi = 0;
double sum=0.0;
double step =1./static_cast<double>(numSteps);
for (int i=0; i<numSteps; i++)
{
x = (i + .5)*step;
sum = sum + function(x);
}
pi = sum*step;
return pi;
}
int main(int argc, char** argv)
{
double timeStart ,timeStop;
double pi;
double secs;
timeStart = omp_get_wtime();
pi = CalcIntegral(8,0);
timeStop = omp_get_wtime();
std::cout << "The value of integral is " << pi << " Error is " << fabs(pi - PI25DT) << std::endl;
std::cout << "The time to calculate integral was " ;
secs= timeStop - timeStart;
std::cout << secs << " seconds\n" << std::endl;
timeStart = omp_get_wtime();
pi = CalcIntegralWithParallel(4);
timeStop = omp_get_wtime();
std::cout << "The value of PI is OPEN MP 4 " << pi << " Error is " << fabs(pi - PI25DT) << std::endl;
std::cout << "The time to calculate PI was " ;
secs= timeStop - timeStart;
std::cout << secs << " seconds\n" << std::endl;
timeStart = omp_get_wtime();
pi = CalcIntegralWithParallel(8);
timeStop = omp_get_wtime();
std::cout << "The value of PI is OPEN MP 8 " << pi << " Error is " << fabs(pi - PI25DT) << std::endl;
std::cout << "The time to calculate PI was " ;
secs= timeStop - timeStart;
std::cout << secs << " seconds\n" << std::endl;
timeStart = omp_get_wtime();
pi = CalcIntegralWithParallel(12);
timeStop = omp_get_wtime();
std::cout << "The value of PI is OPEN MP 12 " << pi << " Error is " << fabs(pi - PI25DT) << std::endl;
std::cout << "The time to calculate PI was " ;
secs= timeStop - timeStart;
std::cout << secs << " seconds\n" << std::endl;
return 0;
}
Ниже результат выполнения программы:
The value of integral is 3.14159 Error is 7.54952e-15 The time to calculate integral was 11.9711 seconds
The value of PI is OPEN MP 4 3.14162 Error is 2.64888e-05 The time to calculate PI was 20.342 seconds
The value of PI is OPEN MP 8 3.14159 Error is 3.7927e-07 The time to calculate PI was 21.1447 seconds
The value of PI is OPEN MP 12 3.14162 Error is 3.16601e-05 The time to calculate PI was 21.4869 seconds
В общем, как я и говорил, все дело в роли для x. Если программу оставить как есть, то тогда при оптимизации gcc все делает правильно сам, а без оптимизации для x отводится роль общей переменной для потоков (shared - я проверил, установив эту роль для x). Из-за этого получается неверный результат (очень низкая точность) и коллизии при попытке нескольких потоков одновременно записать в эту x. Лечится принудительным указанием, что x должна быть приватной для каждого потока (лучше через firstprivate, чтобы она унаследовала и начальное значение, но это уже не так важно в данной задаче).
Такая прагма решает проблему при неоптимизированной сборке g++ omp.cpp -o o -fopenmp:
#pragma omp parallel for num_threads(countThread) reduction(+:sum) firstprivate(x)
У меня на i5 Haswell (4 ядра) получились следующие результаты:
The value of integral is 3.14159 Error is 2.05835e-012 The time to calculate integral was 16.973 seconds
The value of PI is OPEN MP 4 3.14159 Error is 3.55715e-013 The time to calculate PI was 4.556 seconds
The value of PI is OPEN MP 8 3.14159 Error is 1.24345e-013 The time to calculate PI was 4.321 seconds
The value of PI is OPEN MP 12 3.14159 Error is 1.22125e-013 The time to calculate PI was 4.415 seconds
что является вполне нормальным на мой взгляд.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости