使用AVX AVX2和OpenMP进行中值过滤

时间:2018-11-29 12:07:16

标签: x86 openmp vectorization avx avx2

我正在使用avx avx2指令和OpenMP进行中值过滤。输入的是4K图片。一次,该算法可处理从输入中获取的像素的单个颜色分量。

我的过滤器大小为5*5 = 25。要对中值进行过滤,我必须对这些unsigned char号进行排序,然后取中间的一个。我正在使用Batcher的Odd-Even mergesort,而且效果很好。

那时我需要尽我所能加快算法的速度。我对该程序进行了多次测试,平均结果为3.08秒

可视化排序算法:您可以看到整个排序过程可以分为15个较小的步骤。 Visualization of the sorting algorithm


我有一个顶级函数,可以从名为MedianFiltering的主体中调用,该函数获取进行过滤所需的所有信息,并使用指针将其写回。调用此函数时,它将为以下两个函数创建所有必需的控制向量:

_mm256_blendv_epi8()_mm256_permute2f128_si256()

创建所有必需的控制向量

我下一行有40个(所有名称都不同)

__m256i vectorControl= _mm256_lddqu_si256((__m256i *)controlArray);

类似于

__m256i vmaskBlendControlFromMinMaxandWorkingOn4 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinMaxandWorkingOn4);

__m256i vmaskBlendControlFromMinandMax5 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinandMax5);
__m256i vmaskBlendControlFromMinMaxandWorkingOn5 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinMaxandWorkingOn5);

__m256i vmaskBlendControlFromMinandMax6 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinandMax6);

__m256i vmaskBlendControlFromMinandMax7 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinandMax7);
__m256i vmaskBlendControlFromMinMaxandWorkingOn7 = _mm256_lddqu_si256((__m256i *)maskBlendControlFromMinMaxandWorkingOn7);

我想我不需要把所有的想法都发布出来。

算法

然后进行排序:

//stepping on every row
for (int row = 0; row < imgHeight; row++)
{
    stepping on every column of the picture

    for (int col = 0; col < imgWidth; col++)
    {
        OneColorChanelWidth calculatedMedians[3] = { 0 };
        //calculating each color of a single pixel
        for (int rgba = 0; rgba < 3; rgba++)
        {
            OneColorChanelWidth calcMedian[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255 };
            for (int fy = 0; fy < FILTER_W; fy++)
            {
                for (int fx = 0; fx < FILTER_H; fx++)
                {
                    calcMedian[fy * 5 + fx] = *(imgSrcExt + (row + fy)*imgWidthF * 3 + (col + fx) * 3 + rgba);
                }
            }
            __m256i vinput = _mm256_lddqu_si256((__m256i *)calcMedian);


              *Sorting the calcMedian array all the 15 steps are here the result is stored in workingOn*



            *(imgDstMedian + row*imgWidth * 3 + col * 3 + rgba) = workingOn.m256i_u8[12];
        }
    }
}

鸟瞰点:

void MedianFiltering(arguments)
{

   Creating all the required control vectors

   Algorithm

   return;
}

由于我可以使用OpenMP,因此并行化可以很好地提高处理速度。我将#pragma omp parallel for放在按行计数但没有任何更改的for循环的前面。然后,我将其放在按行计数的前面,没有速度增益。

在此之后,我正在考虑的问题可能是所有启动的线程都使用相同的控制向量(它们都是通过方式读取的),请告诉我这是否会导致并行化没有任何区别。 / p>

我已经做过一个实验:我将并行化编译指示放在代码中的不同位置并运行测试,但是不幸的是,没有一个实验显示出速度的提高。 实际上,我得到的最短时间是3.08秒,但这可以在没有任何并行性的情况下实现。

有没有一种方法可以使用并行化来改善我的处理时间?另一种方法是涉及重做排序过程,但是我对此不感兴趣。

0 个答案:

没有答案