Я изучаю openmp, используя пример вычисления значения pi через квадратуру. В последовательной, я бегу следующий код C:Оптимизация компилятора OpenMP vs gcc
double serial() {
double step;
double x,pi,sum = 0.0;
step = 1.0/(double) num_steps;
for (int i = 0; i < num_steps; i++) {
x = (i + 0.5) * step; // forward quadature
sum += 4.0/(1.0 + x*x);
}
pi = step * sum;
return pi;
}
Я сравнивая это с реализацией OMP, используя параллельно с уменьшением для:
double SPMD_for_reduction() {
double step;
double pi,sum = 0.0;
step = 1.0/(double) num_steps;
#pragma omp parallel for reduction (+:sum)
for (int i = 0; i < num_steps; i++) {
double x = (i + 0.5) * step;
sum += 4.0/(1.0 + x*x);
}
pi = step * sum;
return pi;
}
Для num_steps = 1000000000 и 6 нитей в случай OMP, компилировать и время:
double start_time = omp_get_wtime();
serial();
double end_time = omp_get_wtime();
start_time = omp_get_wtime();
SPMD_for_reduction();
end_time = omp_get_wtime();
не используя куб.см оптимизации компилятора, среды выполнения вокруг 4s (последовательный) и .66s (OMP). С флагом -O3 серийное время выполнения падает до «.000001s», а время выполнения omp в основном не изменяется. Что тут происходит? Используются ли эти векторные инструкции, или это плохой код или метод синхронизации? Если это векторизация, почему функция omp не пользуется?
Может показаться, что используемая мной машина использует современный 6-ядерный процессор Xeon.
Спасибо!
Как насчет просмотра выхода компилятора (код сборки)? – MikeCAT
https://en.wikipedia.org/wiki/Dead_code_elimination – Mysticial
Известно ли значение num_steps во время компиляции? Если это так, вы можете попытаться передать его как параметр времени выполнения через stdin. Посмотрите, если это имеет значение. Если его значение жестко закодировано, возможно, компилятор может заменить цикл for простым выражением, имеющим эквивалентный результат. – RunFun