Использование OpenMP для оптимизации билинейной интерполяции

Я работаю над ARM, и я пытаюсь оптимизировать уменьшение изображения, я использовал OpenCV cv :: resize и его медленный ~ 3 мс для 1280 * 960 до 400 * 300, я пытаюсь использовать OpenMP для его ускорения Однако при выставлении параллели для оператора изображение было искажено. Я знаю, что это связано с частными переменными и общими данными между потоками, но я не могу найти проблему.

void  resizeBilinearGray(uint8_t *pixels, uint8_t *temp, int w, int h, int w2, int h2) {

int A, B, C, D, x, y, index, gray ;
float x_ratio = ((float)(w-1))/w2 ;
float y_ratio = ((float)(h-1))/h2 ;
float x_diff, y_diff;
int offset = 0 ;#pragma omp parallel for
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w+x ;

// range is 0 to 255 thus bitwise AND with 0xff
A = pixels[index] & 0xff ;
B = pixels[index+1] & 0xff ;
C = pixels[index+w] & 0xff ;
D = pixels[index+w+1] & 0xff ;

// Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
gray = (int)(
A*(1-x_diff)*(1-y_diff) +  B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff)   +  D*(x_diff*y_diff)
) ;

temp[offset++] = gray ;
}
}

}

1

Решение

Почему бы вам не попробовать заменить temp [offset ++] на temp [i * w2 + j]?

Ваше смещение имеет несколько проблем. Для одного это имеет условие гонки. Но хуже всего то, что OpenMP назначает очень разные значения i и j для каждого потока, поэтому они читают несмежные части памяти. Вот почему ваше изображение искажено.

Помимо OpenMP, есть несколько других способов ускорить ваш код, которые вы можете попробовать. Я не знаю ARM, но на Intel вы можете получить большую скорость с SSE. Кроме того, вы можете попробовать фиксированную с плавающей точкой. Я нашел ускорения с обеих сторон в билинейной интерполяции.
fastcpp.blogspot.no/2011/06/bilinear-pixel-interpolation-using-sse.html

2

Другие решения

Я думаю, что ваша проблема offset переменная. Поскольку многие потоки могут работать одновременно, вы никогда не знаете, какой поток будет обновлять смещение первым. Вот почему полученное изображение искажается.

Лучшая стратегия состоит в том, чтобы перебрать пиксели полученного изображения. Для каждого полученного пикселя вы находите координаты пикселей исходного изображения, выполняете интерполяцию и записываете результат. Таким образом, вы уверены, что каждый поток работает на разных пикселях и на правильном пикселе.

2

По вопросам рекламы [email protected]