Platform: LG G3, Adreno 330 ,img size 3264x2448


C code

neon

GPU

300

60

29

 单位:ms


1. 目前按如下行列分解的方式最快29ms,Horizontal kernel globalWorksize[1] = {height+256-height%256};Vertical kernel globalWorksize2[1] = {width+256-width%256};

localWorksize2[] = {64}; localWorksize2 手动设为64时最快。

Porfile的结果为:Horizontal kernel wait time 11ms,实际rum time 18ms.

这个wait time是什么呢?注释掉Horizontal kernel中的 vstore16(convert_uchar16(sum>>(ushort)8),0,pOutLine+j) ; wait time只有0.x ms.并且 localWorksize 越小wait time越长,1时达到200ms,1620ms. 难道是写内存等待时间,没有足够的ALU指令隐藏访存延时?写内存后进入下一个for循环,马上又读内存,所以没有ALU指令隐藏这个延时。然而Horizontal kernelprofile结果实际run time只有0.x ms,所有时间基本都是在wait.(更正:注释掉vstore16,sum的计算被优化掉了,0.x ms是读内存的时间)

 

__kernel void ImageGaussianFilterHorizontal(__global const uchar* restrict source, // Source image
                            __global uchar* restrict  dest,  // Intermediate dest image
                                             const int imgWidth ,                // Image width
                                             const int imgHeight)
{
    const int y = get_global_id(0);
    if(y>=(imgHeight))
        return;
    const uchar m_nRightShiftNum = 8;
    const uchar Rounding = (1 << (m_nRightShiftNum - 1));
    const uchar  m_nFilter[11] = {1,4,8,16,32,134,32,16,8,4,1};

    const int s = 11;
    const int nStart = 5;
    const int nWidth = imgWidth;

    __global const uchar* pInLine = source + y*nWidth;
    __global uchar* pOutLine = dest + y*nWidth;
    int j;
    for(j = 0; j < nStart; j ++)
    {
        ushort sum = 0;

        for (int m = 0; m<s / 2; m++)
        {
            int k1 = (j + m - nStart);
            k1 = k1<0 ? -k1 : k1;

            int k2 = (j + nStart - m );
            sum += (pInLine[k1] + pInLine[k2])*m_nFilter[m];
        }
        sum += pInLine[j] * m_nFilter[s / 2];
        sum = (sum + Rounding) >> 8;
        pOutLine[j] = (uchar)clamp(sum,(ushort)0,(ushort)255);
    }

    for ( ; (j+16)<= (nWidth - nStart); j+=16)
    {        
#define GAUSSIAN_LINE_NEON(m) \
sum += ( convert_ushort16(vload16(0,pInLine+j-nStart+m))* m_nFilter[m] );

        ushort16 sum =  (convert_ushort16(vload16(0,pInLine+j-nStart)) * m_nFilter[0]);
        GAUSSIAN_LINE_NEON(1);
        GAUSSIAN_LINE_NEON(2);
        GAUSSIAN_LINE_NEON(3);
        GAUSSIAN_LINE_NEON(4);
        GAUSSIAN_LINE_NEON(5);
        GAUSSIAN_LINE_NEON(6);
        GAUSSIAN_LINE_NEON(7);
        GAUSSIAN_LINE_NEON(8);
        GAUSSIAN_LINE_NEON(9);
        GAUSSIAN_LINE_NEON(10);

        sum += (ushort)Rounding;
        vstore16(convert_uchar16(sum>>(ushort)8),0,pOutLine+j) ;
    }

    for( ; j < nWidth; j ++)
    {
        ushort sum = 0;

        for (int m = 0; m<s / 2; m++)
        {
            int k1 = (j + m - nStart);

            int k2 = (j + nStart - m );
            k2 = k2 >= nWidth ? 2 * nWidth - 2 - k2 : k2;
            sum += (pInLine[k1] + pInLine[k2])*m_nFilter[m];
        }
        sum += pInLine[j] * m_nFilter[s / 2];
        sum = (sum + Rounding) >> m_nRightShiftNum;
        pOutLine[j] =  (uchar)clamp(sum,(ushort)0,(ushort)255);
    }
}


__kernel void ImageGaussianFilterVertical( __global uchar* restrict source,   // Intermediate image processed by ImageGaussianFilterHorizontal()
                        __global uchar* restrict dest,  // Final destination image
                        const int imgWidth,
                                         const int imgHeight
                                    )
{
    const int x = get_global_id(0);
    if(x>=(imgWidth))
        return;
    const int x_offset = x;

    const int s = 11;
    const int nStart = s / 2;
    const int m_nRightShiftNum = 8;
    const int Rounding = (1 << (m_nRightShiftNum - 1));
    const uchar  m_nFilter[11] = {1,4,8,16,32,134,32,16,8,4,1};

    int y;
//    mem_fence(CLK_LOCAL_MEM_FENCE);

    ushort lines[11];
    lines[nStart] = (ushort)( source[x_offset]  );
    for(y=1;y<=nStart;y++)
    {
        lines[nStart+y] = (ushort)( source[y*imgWidth+x_offset]  );
        lines[nStart-y] = lines[nStart+y];
    }

    for(y=0;y<(imgHeight-nStart-1);)
    {

        ushort sum = lines[nStart] * m_nFilter[nStart];
#define    GaussianTwoLines(m) \
    sum += ( (lines[m] + lines[s-1-m])*m_nFilter[m] );
        GaussianTwoLines(0)
        GaussianTwoLines(1)
        GaussianTwoLines(2)
        GaussianTwoLines(3)
        GaussianTwoLines(4)

        sum += (ushort)Rounding;
        dest[y*imgWidth+x_offset]  = (uchar)(sum>>(ushort)8);

        y++;
        for(int i = 0; i<s-1; i++) lines[i] = lines[i+1];
        
        lines[s-1] =  (ushort)( source[(y+nStart)*imgWidth+x_offset]  );
        
    }

    for(y=imgHeight-nStart-1;y<(imgHeight-1);)
    {
        ushort sum = lines[nStart] * m_nFilter[nStart];
        GaussianTwoLines(0)
        GaussianTwoLines(1)
        GaussianTwoLines(2)
        GaussianTwoLines(3)
        GaussianTwoLines(4)

        sum += (ushort)Rounding;
        dest[y*imgWidth+x_offset]  = (uchar)(sum>>(ushort)8);

        y++;
        for(int i = 0; i<s-1; i++) {
            lines[i] = lines[i+1];
        }
        lines[s-1] = lines[(imgHeight-y)*2-2] ; //
    }
    //last y=imgHeight-1
    ushort sum = lines[nStart] * m_nFilter[nStart];
    GaussianTwoLines(0)
    GaussianTwoLines(1)
    GaussianTwoLines(2)
    GaussianTwoLines(3)
    GaussianTwoLines(4)

    sum += (ushort)Rounding;
    dest[y*imgWidth+x_offset]  = (uchar)(sum>>(ushort)8);
}
kernel

相关文章:

  • 2021-11-12
  • 2021-10-07
  • 2021-06-24
  • 2022-12-23
  • 2021-06-26
  • 2021-08-24
  • 2021-09-07
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-03
相关资源
相似解决方案