提高OpenCL图像处理的速度

时间:2017-03-05 22:32:25

标签: image-processing kernel opencl

我认为我内核的执行时间太长了。它的作用是使用加法,减法,除法或乘法将两个图像混合在一起。

#define SETUP_KERNEL(name, operator)\
 __kernel void name(__read_only image2d_t image1,\
                        __read_only image2d_t image2,\
                       __write_only image2d_t output,\
                       const sampler_t sampler1,\
                       const sampler_t sampler2,\
                       float opacity)\
{\
    int2 xy = (int2) (get_global_id(0), get_global_id(1));\
    float2 normalizedCoords = convert_float2(xy) / (float2) (get_image_width(output), get_image_height(output));\
    float4 pixel1 = read_imagef(image1, sampler1, normalizedCoords);\
    float4 pixel2 = read_imagef(image2, sampler2, normalizedCoords);\
    write_imagef(output, xy, (pixel1 * opacity) operator pixel2);\
}

SETUP_KERNEL(div, /)
SETUP_KERNEL(add, +)
SETUP_KERNEL(mult, *)
SETUP_KERNEL(sub, -)

如您所见,我使用宏来快速定义不同的内核。 (我应该更好地使用函数吗?) 不知怎的,内核设法在GTX 970上花了3ms。 我该怎么做才能提高这个特定内核的性能? 我应该把它分成不同的程序吗?

2 个答案:

答案 0 :(得分:1)

分部通常是费用的 我建议将normalizedCoords的计算移到主机端。

在主持人方面:

float normalized_x[output_width]; // initialize with [0..output_width-1]/output_width
float normalized_y[output_height]; // initialize with [0..output_height-1]/output_height

将内核更改为:

#define SETUP_KERNEL(name, operator)\
 __kernel void name(__read_only image2d_t image1,\
                        __read_only image2d_t image2,\
                       __write_only image2d_t output,\
                       global float *normalized_x, \
                       global float *normalized_y, \
                       const sampler_t sampler1,\
                       const sampler_t sampler2,\
                       float opacity)\
{\
    int2 xy = (int2) (get_global_id(0), get_global_id(1));\
    float2 normalizedCoords = (float2) (normalized_x[xy.x],normalized_y[xy.y] );\
    float4 pixel1 = read_imagef(image1, sampler1, normalizedCoords);\
    float4 pixel2 = read_imagef(image2, sampler2, normalizedCoords);\
    write_imagef(output, xy, (pixel1 * opacity) operator pixel2);\
}

此外,您可以尝试使用相同的技术不使用标准化的cooardinates。 如果输入图像的大小不经常改变,这将更有利。

答案 1 :(得分:1)

双线性插值比最近邻方法慢2x-3x。你确定你没有在opengl中使用最近邻居吗?

它在后台(由采样器)执行的操作类似于:

R1 = ((x2 – x)/(x2 – x1))*Q11 + ((x – x1)/(x2 – x1))*Q21

R2 = ((x2 – x)/(x2 – x1))*Q12 + ((x – x1)/(x2 – x1))*Q22

After the two R values are calculated, the value of P can finally be calculated by a weighted average of R1 and R2.

P = ((y2 – y)/(y2 – y1))*R1 + ((y – y1)/(y2 – y1))*R2

The calculation will have to be repeated for the red, green, blue, and optionally the alpha component of.

http://supercomputingblog.com/graphics/coding-bilinear-interpolation/

或者只是Nvidia实现了opengl的快速路径和opencl图像访问的完整路径。例如,对于amd,图像写入是完整路径,小于32位数据访问是完整路径,图像读取是快速路径。

另一种选择:Z顺序更适合于那些图像数据的计算分歧,而opencl的非Z顺序(可疑,可能不是)更糟。