У меня есть этот C-код, который мне нужно оптимизировать с помощью OpenMP, я не могу написать оригинальный код, но вот суррогат:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef _OPENMP
#include <omp.h>
#endif
void Funct(double *vec, int len)
{
int i;
double tmp;
//Section 1
#pragma omp parallel for
for ( i = 0; i < len; i++ ) //Code that initialize vec, it simulates an initialization in the original code
vec [ i ] = i;
//Section 2
//This code must be run sequentially
tmp = vec [ 0 ];
vec [0 ] = vec [ len - 1 ];
vec [ len - 1 ] = tmp;
tmp = vec [ 0 ];
vec [0 ] = vec [ len - 1 ];
vec [ len - 1 ] = tmp;
//End of the sequential code
//Section 3
#pragma omp parallel for
for ( i = 0; i < len; i++ ) //Code to simulate loadwork on vec
{
vec [ i ] = pow(vec[i], 2 );
vec [ i ] = sqrt ( vec [ i ] );
vec [ i ] += 1;
vec [ i ] = pow(vec[i], 2 );
vec [ i ] = sqrt ( vec [ i ] );
vec [ i ] -= 1;
}
}
int main ()
{
double *vec;
int i;
vec = (double *) malloc ( sizeof ( double ) * 5104 ); //Length of the vector in the original code
for ( i = 0; i < 1000000; i++ ) //Iteration in the original code
Funct(vec, 5104 );
for ( i = 0; i < 5; i++ ) // Access the array to avoid -O2 cancellations
printf ("%.2f ", vec [ i * 1000 ] );
return 0;
}
В Funct, разделы 1, 2 и 3 должныисполняться последовательно;Раздел 2 строго последовательный.
В исходном коде я вынужден использовать распараллеливание внутри функции Funct (...), поэтому, к сожалению, стоимость создания потоков умножается на числоитераций, но это не проблема, так как это все еще позволяет некоторую оптимизацию времени, когда возникает внутренняя длина for main или vec (если у вас есть предложения, я очень открыт для прослушивания).Проблема в «Разделе 2», фактически он заставляет OMP создать барьер или ожидание, но это замедляет выполнение;Если я удаляю этот раздел, я получаю довольно приемлемую оптимизацию по отношению к последовательному коду;к сожалению, я не могу.Я попробовал omp single, omp критический и т. Д., Чтобы увидеть, назначил ли бы он код некоторым потокам в предыдущем пуле, но нет, есть ли способ сделать его более производительным?(Как резко изменить прагмы, не проблема)
(Скомпилировано с gcc file.c -o file.out -lm -O2 -fopenmp, протестировано в Linux Lubuntu с использованием time ./file.out)
Редактировать 1: Я хотел бы отметить, что
tmp = vec [ 0 ];
vec [0 ] = vec [ len - 1 ];
vec [ len - 1 ] = tmp;
tmp = vec [ 0 ];
vec [0 ] = vec [ len - 1 ];
vec [ len - 1 ] = tmp;
Это просто случайный код, который я поместил в метод, чтобы прояснить, что он должен выполняться последовательно (он выполняет одну и ту же операцию два раза, меняет местами vec [0] и vec [len - 1], поэтому в конце выполнения ничего не происходит);Вместо этого я мог бы написать любую другую функцию или код;
Например, я мог бы поставить
Foo1();
Foo2();
Foo3();