2013-03-15 2 views
1

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

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 ; 
     } 
    } 

} 

ответ

2

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

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

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

+0

так что вы думаете, что i, k должны быть частными переменными? как насчет другой вложенной петли? После того, как я попробую это, я попробую ARM Neon –

+0

i и j уже являются частными переменными в силу определения после прагмы openmp. Вы попробовали мое предложение? – 2013-03-16 13:15:22

+0

Если вы хотите получить дополнительную информацию о вложенности петли, см. Эту ссылку. Но это не повлияет на искажение изображения. Это связано с тем, как вы используете смещение. Вам нужно заменить temp [offset ++] на temp [i * w2 + j] http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause – 2013-03-16 13:19:52

2

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

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

Смежные вопросы