我试图在OpenCL中为圆圈实现Hough变换,但我遇到了非常奇怪的问题。每次我运行Hough内核时,我最终会得到略有不同的累加器,即使参数相同而且累加器总是一个刚刚归零的表(例如http://imgur.com/a/VcIw1)。我的内核代码如下:
#define BLOCK_LEN 256
__kernel void HoughCirclesKernel(
__global int* A,
__global int* imgData,
__global int* _width,
__global int* _height,
__global int* r
)
{
__local int imgBuff[BLOCK_LEN];
int localThreadIndex = get_local_id(0); //threadIdx.x
int globalThreadIndex = get_local_id(0) + get_group_id(0) * BLOCK_LEN; //threadIdx.x + blockIdx.x * Block_Len
int width = *_width; int height = *_height;
int radius = *r;
A[globalThreadIndex] = 0;
barrier(CLK_GLOBAL_MEM_FENCE);
if(globalThreadIndex < width*height)
{
imgBuff[localThreadIndex] = imgData[globalThreadIndex];
barrier(CLK_LOCAL_MEM_FENCE);
if(imgBuff[localThreadIndex] > 0)
{
float s1, c1;
for(int i = 0; i<180; i++)
{
s1 = sincos(i, &c1);
int centerX = globalThreadIndex % width + radius * c1;
int centerY = ((globalThreadIndex - centerX) / height) + radius * s1;
if(centerX < width && centerY < height)
atomic_inc(A + centerX + centerY * width);
}
}
}
barrier(CLK_GLOBAL_MEM_FENCE);
}
这可能是我如何递增累加器的错误吗?
答案 0 :(得分:0)
if(globalThreadIndex < width*height)
{
imgBuff[localThreadIndex] = imgData[globalThreadIndex];
barrier(CLK_LOCAL_MEM_FENCE);
...
}
这是未定义的行为,因为分支内部存在障碍。
计算单元中的所有流媒体单元必须输入相同的内存栅栏。
试试这个:
if(globalThreadIndex < width*height)
{
imgBuff[localThreadIndex] = imgData[globalThreadIndex];
...
}
barrier(CLK_LOCAL_MEM_FENCE);
如果您使用多个设备,可能还有其他问题:
get_local_id(0) + get_group_id(0)
这里get_group_id(0)获取每个设备的组ID,它从所有设备的0开始,就像get_global_id也开始为零一样;所以你应该在&#34; ndrange&#34;中添加适当的偏移量。使用多个设备时的说明。尽管不同的设备可以支持相同的浮点精度要求,但其中一个可能提供比其他设备更好的精度,并且可以给出略微不同的结果。如果它是单个设备,那么你应该尝试降低gpu频率,因为它可能有超频的缺陷或副作用。