这是我制作的代码草案:
void __kernel myKernel(__global const short* input,
__global short* output,
const int width,
const int height){
// Always square. (and 16x16 in our example)
const uint local_size = get_local_size(0);
// Get the work-item col/row index
const uint wi_c = get_local_id(0);
const uint wi_r = get_local_id(1);
// Get the global col/row index
const uint g_c = get_global_id(0);
const uint g_r = get_global_id(1);
// Declare a local array NxN
const uint arr_size = local_size *local_size ;
__local short local_in[arr_size];
// Transfer the global memory for into a local one.
local_in[wi_c + wi_r*local_size ] = input[g_c + g_r*width];
// Wait that all the work-item are sync
barrier(CLK_LOCAL_MEM_FENCE);
// Now add code to process on the local array (local_in).
据我了解OpenCL工作组/工作项,我需要做的是将全局16x16 ROI从全局内存复制到本地内存。 (如果我错了,请纠正我,因为我从此开始)。
因此,在屏障之后,local_in中的每个元素都可以通过wi_c + wi_r*local_size
进行访问。
但现在让我们做一些棘手的事情。如果我希望我的工作组中的每个工作项都能在3x3邻域上工作,那么我需要一个18x18的local_in数组。
但是如何创造呢?因为我只有16x16 = 256个工作项(线程),但我需要18x18 = 324(缺少68个线程来做)。
我的基本想法应该是:
if(wi_c == 0 && wi_r == 0){
// Code that copy the border into the new array that should be
// local_in[(local_size+2)*(local_size+2)];
}
但这很糟糕,因为第一个工作项目(第一个线程)将必须处理所有边界,而该组中的其余工作项目将只等待第一个工作项目完成。 (再次,这是我对OpenCL的理解,可能是错误的。)
所以这是我真正的问题:
答案 0 :(得分:0)
我尝试了不同的方法,但我选择了最终版本,而不是#34;如果"并尽可能地使用线程(在第二阶段,可能不是完全有效的,因为很少有线程空闲,但它是我能够获得的最好的)。
原理是在左上角设置原点(起始位置),并使用循环索引从该位置创建读/写索引。循环从2D中的本地id位置开始。所以所有256个工作项都写出了他们的第一个元素,而在第二个阶段,只有68个工作项在256上完成了2个底行+2个右列。
我还不是OpenCL专家,所以这仍然可以有更多改进(可能循环展开,我不知道)。
__local float wrkSrc[324];
const int lpitch = 18;
// Add halfROI to handle the corner
const int lcol = get_local_id(0);
const int lrow = get_local_id(1);
const int2 gid = { col, row };
const int2 lid = { lcol, lrow };
// Always get the most Top-left corner of that ROI to extract.
const int2 startPos = gid - lid - halfROI;
// Loop on each thread to get their right ID.
// Thread with id < 2 * halfROI will process more then others, but not that much an issue.
for ( int x = lid.x; x < lpitch; x += 16 ) {
for ( int y = lid.y; y < lpitch; y += 16 ) {
// Get the position to write into the local array.
const int lidx = x + y * lpitch;
// Get the position to read into the global memory (src)
const int2 readPos = startPos + (int2)( x, y );
// Is inside ?
if ( readPos.x >= 0 && readPos.x < width && readPos.y >= 0 && readPos.y < height )
wrkSrc[lidx] = src[readPos.x + readPos.y * lab_new_pitch];
else
wrkSrc[lidx] = 0.0f;
}
}