如何将行处理内核过滤和列处理内核过滤合并到单个openCL内核中

如何将行处理内核过滤和列处理内核过滤合并到单个openCL内核中,c,optimization,opencl,C,Optimization,Opencl,我在openCL中使用行和列处理实现了图像处理过滤器,其中大部分处理在启动多个内核本身时被浪费 因此,我可以将这两个内核合并到一个内核中,该内核具有相同的功能,在Intel HD4600图形卡中性能更好。有关守则的详情如下:- 假设: 1.水平和垂直填充均由主机完成(c编程) 2.N(过滤器长度为8,宽度和高度为1024 x 1024,使用通用过滤器生成过滤器系数 3.使用下面的API启动第一行和第二列内核 ret |=clEnqueueNDRangeKernel(命令队列,内核,2,空,全局(

我在openCL中使用行和列处理实现了图像处理过滤器,其中大部分处理在启动多个内核本身时被浪费

因此,我可以将这两个内核合并到一个内核中,该内核具有相同的功能,在Intel HD4600图形卡中性能更好。有关守则的详情如下:-

假设:
1.水平和垂直填充均由主机完成(c编程)
2.N(过滤器长度为8,宽度和高度为1024 x 1024,使用通用过滤器生成过滤器系数
3.使用下面的API启动第一行和第二列内核
ret |=clEnqueueNDRangeKernel(命令队列,内核,2,空,全局(1024x1024),空,0,空,空);

//代码:

__kernel void filter_rows(__global float *ip_img,__global float *op_img,
                          int width, int height,int pitch,int N,__constant float *W)
{
    __private int i=get_global_id(0); 
    __private int j=get_global_id(1); 
    __private int k;
    __private float a;
    __private int image_offset = N*pitch +N;
    __private int curr_pix = j*pitch + i +image_offset;
    // apply filter
    for(k=-N, a=0.0f; k<=N; k++)
    {
    a += ip_img[curr_pix+k] * W[k+N];
    }
    op_img[curr_pix] = a;   
}
__kernel void filter_col(__global float *ip_img,__global float *op_img,int width,
                         int height,int pitch,int N,__constant float *W)
{
    __private int i=get_global_id(0);
    __private int j=get_global_id(1);
    __private int k;
    __private float a;
    __private int image_offset = N*pitch +N;
    __private int curr_pix = j*pitch + i +image_offset;

    // apply filter
    for(k=-N, a=0.0f; k<=N; k++)
    {
      a += ip_img[k*pitch +curr_pix] * W[k+N];                  
    }
    op_img[curr_pix] = a;
}
void padd_hor(float *ip_img,pad_leng)
{
    //...using simple C programming
}
void padd_ver(float *ip_img,pad_leng)
{
    //...using simple c programming
}
void generic_filter(_global float *in_image,__global float *out_image,
__global float *temp_image,int width, int height,int pitch,int N,
__constant float *Wr,__constant float *Wc)
{
    padd_hor(in_image,filter_length)
    filter_rows(in_image,temp_image,width,height,pitch,filter_length,filter_coeff_hor);
    pad_ver(temp_image,filter_length)
    filter_col(temp_image,out_image,width,height,pitch,filter_length,filter_coeff_ver);
}
__kernel generic_filter(_global float *in_image,__global float *out_image,__global      float*temp_image,
int width, int height,int pitch,int N,__constant float *Wr,__constant float *Wc)
{
    // ... here i need your suggetion to implement the kernel which do same as generic_filter
}
\uuuuu内核无效筛选器行(\uuuu全局浮点*ip\u img,\uuuu全局浮点*op\u img,
整数宽度、整数高度、整数间距、整数N、_常数浮点*W)
{
__private int i=get_global_id(0);
__private int j=get_global_id(1);
__私人INTK;
__私人浮动a;
__专用int图像_偏移=N*间距+N;
__专用int curr\u pix=j*基音+i+图像偏移;
//应用过滤器

对于(k=-N,a=0.0f;kI不会合并它,因为您正在进行矩形图像过滤。这种类型的算法适用于单独的过程,行和列,因此两个单独的调用是更容易和更快的事情。您应该做的是向它添加本地内存,因为邻居读取重叠的内存区域。还有,维度的顺序(X,Y)或(Y,X)可能会影响合并,也请检查。同意。可分离筛选器必须按顺序运行,这意味着您不能在单个内核中同时执行这些过程(因为您不能执行全局同步)。您会发现,由于合并读取,优化的垂直过程比优化的水平过程快。解决方案是添加一个旋转过程,允许您使用垂直过程两次。旋转必须使用共享本地内存,以使读取和写入都快。只是更新,我们使用上述技术获得增益,but不符合预期。事实上,我正在寻找2倍性能改进的最小增益。请提出您的想法。我已准备好尝试使用16x16块处理合并这两个,但未观察到增益。提供N作为编译时常量也可能有所帮助。