【发布时间】:2014-05-09 20:37:24
【问题描述】:
我是 OpenCL 的新手,我正在尝试计算灰度图像的直方图。我正在 GPU nvidia GT 330M 上执行此计算。
代码是
__kernel void histogram(__global struct gray * input, __global int * global_hist, __local volatile int * histogram){
int local_offset = get_local_id(0) * 256;
int histogram_global_offset = get_global_id(0) * 256;
int offset = get_global_id(0) * 1920;
int value;
for(unsigned int i = 0; i < 256; i++){
histogram[local_offset + i] = 0;
}
barrier(CLK_LOCAL_MEM_FENCE);
for(unsigned int i = 0; i < 1920; i++){
value = input[offset + i].i;
histogram[local_offset + value]++;
}
barrier(CLK_LOCAL_MEM_FENCE);
for(unsigned int i = 0; i < 256; i++){
global_hist[histogram_global_offset + i] = histogram[local_offset + i];
}
}
此计算是在图像 1920*1080 上执行的。
我正在用
发射内核queue.enqueueNDRangeKernel(kernel_histogram, cl::NullRange, cl::NDRange(1080), cl::NDRange(1));
当直方图的本地大小设置为 256 * sizeof(cl_int) 时,此计算的速度为(通过 nvidia nsight 性能分析)11 675 微秒。
因为本地工作组大小设置为一。我尝试将本地工作组大小增加到 8。但是当我将直方图的本地大小增加到 256 * 8 * sizeof(cl_int) 并使用本地 wg 大小 1 进行计算时。我得到 85 177 微秒。
因此,当我使用每个工作组 8 个内核启动它时,我不会从 11 毫秒获得加速,而是从 85 毫秒获得加速。因此,每个工作组 8 个内核的最终速度为 13 714 微秒。
但是当我创建计算错误时,将 local_offset 设置为零,并且局部直方图的大小为 256 * sizeof(cl_int),并且每个工作组使用 8 个内核,我得到了更好的时间 - 3 854 微秒。
有没有人有一些想法来加快这个计算?
谢谢!
【问题讨论】:
-
您发布的示例代码似乎正在为每个工作项处理一行图像。当您启动每个工作组的多个工作项时,您是否仍在这样做,或者您是否让每个工作组合作处理一行?您能向我们展示您在执行此操作时使用的内核和主机代码吗?
-
感谢您的回复。是的,我使用的是相同的方法,一个线程计算一行。
-
这会导致内存访问性能不佳。理想情况下,您希望合并您的内存访问 - 也就是说,相邻的工作项应该尽可能访问相邻的内存地址。
-
当我在每个工作组的本地内存中使用一个直方图(8 个本地大小)并使用 atom_inc(&histogram[value]);这个计算的速度是 5.5 毫秒,所以它更好,但是,我仍然不明白为什么随着本地内存大小的增加,我的时间会变慢......
-
好的,谢谢,我试试这个