OpenCL代码的优化?

时间:2014-05-15 09:41:05

标签: opencl

我在OpenCL中有一个代码,它从给定的点开始逐步减少数组的元素。

这是代码 - rp是源数组,out是输出数组:

__kernel void subFilter(__global unsigned char* rp,__global unsigned char *out,int istop,int bpp)
{
    int gid = get_global_id(0);//add the offset by bpp to access the next gid
    int i;
    unsigned char temp=0;

    if(gid>=bpp){
         i=gid;
        while(i>=0)
        {
            if((temp + rp[i])>255)
            {
                temp = temp - 256;
                temp=temp + rp[i];
            }
            else
            {
                temp=temp+rp[i];
            }
            i=i-bpp;
        }
        out[gid]=(temp & 0xff);  //masked
        //rp[gid]=66;
    }
    else if(gid<bpp)
    out[gid]=rp[gid];
}

现在这个工作正常但是比在CPU上运行的相同代码花费更多时间。如果循环被移除,也许会更快? 执行时,它的工作原理如下:

rp[0] = rp[0];        // same for rp[1],rp[2],rp[3]
rp[4] = rp[4]+rp[4-4] // steps of 4 till zero
// ...
rp[16]= rp[16]+rp[12]+rp[8]+rp[4]+rp[0]; // etc.

结果rp[i]保存在代码中的temp中,最后保存在out[gid]中 因此,要添加此序列,需要循环,并且需要大量时间... 如果有某种方式,可以缓存前面的总和或者可以完全删除循环,那就太棒了。

如何改进此代码以摆脱循环?

2 个答案:

答案 0 :(得分:0)

首先,我建议你摆脱可能的uchar溢出:

__kernel void subFilter(
    __global unsigned char  *rp,
    __global unsigned char  *out,
    int                     istop,
    int                     bpp)
{
    int gid = get_global_id(0), i = gid;
    unsigned char temp = 0;

    if(gid>=bpp){
        i=gid;

        while(i>=0)
        {
            if(temp > 255 - rp[i])
            {
                temp -= 255 - rp[i];
            }
            else
            {
                temp += rp[i];
            }

            i -= bpp;
        }

        //masked
        out[gid]=(temp & 0xff);  
    }
    else if(gid<bpp){
        out[gid]=rp[gid];
    }
}

回到过滤算法。每个工作项都有唯一的ID,用作循环计数器。通常情况下,这是不好的,因为不同的指令集应用于相同的数据,这违反了SIMD的意识形态。可能,这导致线程分歧和表现下降。你的算法的本质是什么?详细描述。可能是,GPU-amenable实现存在。

答案 1 :(得分:0)

消除循环内的条件代码可能会提高性能:

__kernel void subFilter(__global unsigned char* rp,__global unsigned char *out,int istop,int bpp)
{
    int gid = get_global_id(0);//add the offset by bpp to access the next gid
    int i;
    unsigned char temp=0;

    out[gid]=rp[gid];
    if(gid>=bpp){
        i=gid;
        while(i>=0)
        {
            temp+=rp[i];
            i-=bpp;
        }
        out[gid]=(temp & 0xff);  //masked
    }
}