Мои результаты тестов очень странные.С одной стороны, у меня есть последовательная функция для вычисления квадратичной формы.С другой стороны, я написал две параллельные версии.Для одного потока все функции должны иметь более или менее одинаковое время выполнения.Но одной параллельной функции просто нужна половина времени.Есть ли «скрытая» оптимизация?
Серийная версия:
double quadratic_form_serial(const std::vector<double> & A,const std::vector<double> & v, const std::vector<double> & w){
int N= v.size();
volatile double q=0.0;
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
q +=v[i]*A[i*N+j]*w[j];
return q;
}
Параллельная версия 1:
double quadratic_form_parallel(const std::vector<double> & A,const std::vector<double> & v, const std::vector<double> & w, const int threadnum){
int N= v.size();
omp_set_num_threads(threadnum);
volatile double q[threadnum];
volatile double val = 0.0;
#pragma omp parallel
{
int me = omp_get_thread_num();
q[me] = 0.0;
#pragma omp for collapse(2)
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
q[me]+=v[i]*A[i*N+j]*w[j];
#pragma omp atomic
val+=q[me];
}
return val;
}
Параллельная версия 2:
double quadratic_form_parallel2(const std::vector<double> & A,const std::vector<double> & v, const std::vector<double> & w, const int threadnum){
int N= v.size();
volatile double result =0.0;
omp_set_num_threads(threadnum);
#pragma omp parallel for reduction(+: result)
for (int i=0; i<N; ++i)
for (int j=0; j<N; ++j)
result += v[i] * A[i*N + j] * w[j];
return result;
}
Я запускаю код для N = 10000 и очищаю кэш перед вызовом функции.Функция quadratic_form_parallel2 нуждается в потоке one меньше половины времени, необходимого двум другим функциям:
threads serial Parallel1 Parallel2
1 0.0882503 0.0875649 0.0313441