提高 OpenCL 图像处理速度
Increase speed of OpenCL image processing
我认为我的内核执行时间太长了。它的工作是使用加法、减法、除法或乘法将两个图像混合在一起。
#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 上花费了 3 毫秒。
我可以做些什么来提高这个特定内核的性能?
我应该把它分成不同的程序吗?
除法往往很贵所以
我建议将 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);\
}
您也可以尝试使用相同的技术不使用归一化坐标。
如果输入图像的大小不经常变化,这会更有用。
双线性插值比最近邻法慢 2-3 倍。你确定你没有在 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,image写入是完整路径,小于32bit的数据访问是完整路径,image读取是fastpath。
另一种选择:Z 顺序更适合计算那些图像数据的发散,而 opencl 的非 Z 顺序(可疑,也许不是)更糟糕。
我认为我的内核执行时间太长了。它的工作是使用加法、减法、除法或乘法将两个图像混合在一起。
#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 上花费了 3 毫秒。 我可以做些什么来提高这个特定内核的性能? 我应该把它分成不同的程序吗?
除法往往很贵所以
我建议将 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);\
}
您也可以尝试使用相同的技术不使用归一化坐标。 如果输入图像的大小不经常变化,这会更有用。
双线性插值比最近邻法慢 2-3 倍。你确定你没有在 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,image写入是完整路径,小于32bit的数据访问是完整路径,image读取是fastpath。
另一种选择:Z 顺序更适合计算那些图像数据的发散,而 opencl 的非 Z 顺序(可疑,也许不是)更糟糕。