C++ 利用OpenMP优化双线性插值

C++ 利用OpenMP优化双线性插值,c++,opencv,parallel-processing,openmp,hpc,C++,Opencv,Parallel Processing,Openmp,Hpc,我正在ARM上工作,我正在尝试优化图像的下采样,我使用了OpenCV::resize及其慢速~3ms,用于1280*960到400*300,我试图使用OpenMP来加速它,但是,在使用parallel for语句时,图像被扭曲了。我知道这与线程之间的私有变量和共享数据有关,但我找不到问题所在 void resizeBilinearGray(uint8_t *pixels, uint8_t *temp, int w, int h, int w2, int h2) { int A, B,

我正在ARM上工作,我正在尝试优化图像的下采样,我使用了OpenCV::resize及其慢速~3ms,用于1280*960到400*300,我试图使用OpenMP来加速它,但是,在使用parallel for语句时,图像被扭曲了。我知道这与线程之间的私有变量和共享数据有关,但我找不到问题所在

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

}
void resizeblineargray(uint8_t*像素、uint8_t*温度、int w、int h、int w2、int h2){
int A,B,C,D,x,y,索引,灰色;
浮动x_比率=((浮动)(w-1))/w2;
浮动y_比率=((浮动)(h-1))/h2;
浮动x_diff,y_diff;
整数偏移=0;
#pragma-omp并行

对于(int i=0;i我认为您的问题在于
offset
变量。由于许多线程可以同时工作,您永远不知道哪个线程将首先更新offset。这就是结果图像失真的原因


更好的策略是迭代生成的图像像素。对于每个生成的像素,您可以找到源图像像素的坐标,执行插值,然后写入结果。这样,您就可以确保每个线程在不同的像素和正确的像素上工作。

我认为您的问题在于
偏移量
变量。因为许多线程可以同时工作,您永远不知道哪个线程将首先更新偏移量。这就是结果图像失真的原因


更好的策略是迭代生成的图像像素。对于每个生成的像素,您可以找到源图像像素的坐标,执行插值,然后写入结果。这样,您就可以确保每个线程在不同的像素和正确的像素上工作。

为什么不尝试用temp[i*w2+j]替换temp[offset++]?

偏移量有多个问题。其中一个问题是存在争用条件。但更糟糕的是,OpenMP为每个线程分配了非常不同的i和j值,因此它们读取的是内存的非相邻部分。这就是图像失真的原因

除了OpenMP,您还可以尝试其他几种加速代码的方法。我不知道ARM,但在Intel上,您可以通过SSE获得很大的加速。此外,您可以尝试固定浮点。我在双线性插值中发现了这两种方法的加速。
fastcpp.blogspot.no/2011/06/使用sse.html的双线性像素插值

为什么不尝试用temp[i*w2+j]替换temp[offset++]

偏移量有多个问题。其中一个问题是存在争用条件。但更糟糕的是,OpenMP为每个线程分配了非常不同的i和j值,因此它们读取的是内存的非相邻部分。这就是图像失真的原因

除了OpenMP,您还可以尝试其他几种加速代码的方法。我不知道ARM,但在Intel上,您可以通过SSE获得很大的加速。此外,您可以尝试固定浮点。我在双线性插值中发现了这两种方法的加速。
fastcpp.blogspot.no/2011/06/使用sse.html的双线性像素插值

那么你认为i,k应该是私有变量吗?另一个嵌套循环呢?在我尝试之后,我将尝试ARM Neoni和j已经是私有变量,因为它们是在openmp pragma之后定义的。你尝试过我的建议吗?如果你想了解更多信息关于循环嵌套,请参见此链接。但它不会修复图像失真。这是由于您如何使用偏移量造成的。您需要将temp[offset++]替换为temp[i*w2+j]我只是好奇,你为什么建议他使用SSE over OpenMP,这涵盖了Intel和Arm平台上的矢量化?SSE+AVX正是OpenMP用来完成其工作的!所以你认为I,k应该是私有变量?其他嵌套循环呢?在我尝试之后,我将尝试Arm Neoni和j已经是私有变量了由于是在openmp pragma之后定义的。您尝试过我的建议吗?如果您想了解有关循环嵌套的更多信息,请参阅此链接。但它不会修复图像失真。这是由于您如何使用偏移量。您需要将temp[offset++]替换为temp[i*w2+j]我只是好奇,为什么你建议他使用SSE而不是OpenMP,后者涵盖了Intel和Arm平台上的矢量化?SSE+AVX正是OpenMP用来完成其工作的东西!