Странные результаты тестов для открытых методов mp - PullRequest
0 голосов
/ 30 декабря 2018

Мои результаты тестов очень странные.С одной стороны, у меня есть последовательная функция для вычисления квадратичной формы.С другой стороны, я написал две параллельные версии.Для одного потока все функции должны иметь более или менее одинаковое время выполнения.Но одной параллельной функции просто нужна половина времени.Есть ли «скрытая» оптимизация?

Серийная версия:

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   

1 Ответ

0 голосов
/ 31 декабря 2018

Скорее всего, это результат того, что result является переменной reduction во второй версии OpenMP.Это означает, что каждый поток получает приватную копию result, которая объединяется после параллельной области.Эта частная копия, вероятно, не соответствует изменчивым ограничениям и, следовательно, может быть оптимизирована в большей степени.Я предполагаю, что подробное взаимодействие между volatile и private не определено.

Это показывает, что маркировка переменной как volatile - предположительно, чтобы избежать оптимизации всего кода - является плохой идеей.Вместо этого просто выведите результат.

...