Ухудшение производительности OpenMP с параллельным циклом for - PullRequest
0 голосов
/ 11 ноября 2019

Я применил omp параллельно для конструкции на следующем фрагменте кода (из грубого преобразования)

for (int i = 0; i < sz; i+=2){
        for(k = 0; k < limit; k++){
            theta1 = a - v + ((double) k * step);
            theta2 = b - v + ((double) k * step);
            rho1 = useful_pixels[i]*(h->trigo[(2*k) + 1]) + useful_pixels[i+1] * (h->trigo[2*k]);
            rho2 = useful_pixels[i]* (h->trigo[2*k])  - useful_pixels[i+1]*(h->trigo[(2*k) + 1]);
            hold_index[(i*limit) + (2*k)] = index(rows, cols, rho1, theta1);
            hold_index[(i*limit) + (2*k)+ 1] = index(rows, cols, rho2, theta2);


        }
    }

Я считаю, что не будет условий гонки, поскольку каждая итерация и поток обновляют индекс, отличный от hold_index (целое число)указатель). Может кто-нибудь подсказать, что может быть узким местом? Я получаю на 50% более медленное выполнение с параллельной версией при обработке 300 видеокадров.

В исходном коде потоки создаются в функции, которая вызывается из цикла while для каждого кадра в видео. Время, захваченное утилитой time в linux.

Последовательный: 32,768 с Параллельно: 45 238 с

Компиляция: g ++ stack.cpp -o test_code -std = c ++ 11 -fopenmp

Добавление воспроизводимого примера:

#include <iostream>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctime>
#include <math.h>
#include <omp.h>
#define PI 3.14159265358979323846
using namespace std;

int main()
{
double * trigo;
int *hold_index;
double thetaRadian, thetaDeg = 0;
double hTime;
int rho1,rho2;
double theta1, theta2;
vector<int> pix;
vector<int>::size_type sz;  

trigo = (double *) malloc(64 * sizeof(double) / 0.1);
for (int  i = 0; i < 640; i+= 2)
{
    thetaRadian = (thetaDeg * PI) /  180.0;
    trigo [i] = cos(thetaRadian);
    trigo [i+1] = sin(thetaRadian);
    thetaDeg += 0.1;
}
sz = 3534;

hold_index = (int *)malloc(320*sz*sizeof(int));
for(int h=0; h < 300;h++){
for(int i = 0; i < sz/2; i++) {
    for (int j = 0; j < 2; j++) {
        pix.push_back(i);
        pix.push_back(j);
                }
}
memset(hold_index,0, 320*sz*sizeof(int));
//hTime = omp_get_wtime();  
#pragma omp parallel shared (hold_index)
{
#pragma omp for private(rho1,rho2,theta1,theta2)
for (int i = 0; i < sz; i+=2){
      for(int k = 0; k < 320; k++){
    //cout << "here\n";
        theta1 = 29 + ((double) k * 0.1);
        theta2 = 119 + ((double) k * 0.1);
        rho1 = pix[i]*(trigo[(2*k) + 1]) + pix[i+1] * (trigo[2*k]);
        rho2 = pix[i]* (trigo[2*k])  - pix[i+1]*(trigo[(2*k) + 1]);
        hold_index[(i*320) + (2*k)] = 10;
        hold_index[(i*320) + (2*k)+ 1] = 20;


    }
}}
//hTime = omp_get_wtime() - hTime;



free(hold_index);
pix.clear();}
}
...