OpenCL超出界限错误

时间:2013-09-06 19:12:39

标签: opencl

这个内核工作正常:

__kernel void test(__global float* a_Direction, __global float* a_Output, const unsigned int a_Count)
{
    int index = get_global_id(0);

    if (index < a_Count)
    {
        a_Output[index * 3 + 0] = a_Direction[index * 3 + 0] * 0.5f + 0.5f;
        a_Output[index * 3 + 1] = a_Direction[index * 3 + 1] * 0.5f + 0.5f;
        a_Output[index * 3 + 2] = a_Direction[index * 3 + 2] * 0.5f + 0.5f;
    }
}

此内核产生越界错误:

__kernel void test(__global float3* a_Direction, __global float3* a_Output, const unsigned int a_Count)
{
    int index = get_global_id(0);

    if (index < a_Count)
    {
        a_Output[index].x = a_Direction[index].x * 0.5f + 0.5f;
        a_Output[index].y = a_Direction[index].y * 0.5f + 0.5f;
        a_Output[index].z = a_Direction[index].z * 0.5f + 0.5f;
    }
}

对我来说,似乎他们都应该做同样的事情。 但由于某种原因,这两个作品中只有一个。 我错过了一些明显的东西吗?

确切的错误是:“在GeForce GTX580M(设备0)上执行CL_COMMAND_READ_BUFFER时出现CL_OUT_OF_RESOURCES错误。

2 个答案:

答案 0 :(得分:2)

你可能遇到的问题是你为float3s分配了一个n * 3 * sizeof(float)的缓冲区,但float3的大小和对齐方式是16,而不是12。

答案 1 :(得分:2)

@arsenm在他/她的回答以及@Darkzeros给出了正确的解释,但我觉得开发一点很有意思。问题是在第二个内核中,这些是发生的“隐藏”对齐。正如标准6.1.5。中所述:

  

对于3分量矢量数据类型,数据类型的大小为4 *   的sizeof(组分)。这意味着3分量矢量数据类型将   与4 * sizeof(组件)边界对齐。

让我们用一个例子说明:

假设a_Direction由9个浮点数组成,并且您使用3个线程/工作项来处理这些元素。在第一个内核中,这些都没有问题:线程0将处理索引为0,1,2的元素,线程1处理元素3,4,5,最后,线程2将处理元素6,7,8:所有内容很好。

然而对于第二个内核,假设您使用的数据结构从主机端的角度来看保持不变(即数组从0到8),则线程0将处理元素0,1,2(和也将访问元素4,因为float3类型向量将表现得像一个float4类型向量而不做任何事情)。第二个线程即线程1将不访问元素3,4,5但元素4,5, 6(和7没有做任何事情)。

因此,这就是出现问题的地方,线程2将尝试访问元素8,9,10(和11),因此超出边界访问权限。

总结一下,3个元素的向量就像4个元素的向量。

现在,如果要在主机端不使用数据结构而使用向量,可以使用v2和vstore3函数,如3.12.7节所述。标准。像那样:

 vstore3(vload3(index, a_Direction) * 0.5f + 0.5f, index, a_Output));
顺便说一下,你不必费心这样的陈述(假设一个正确的对齐方式):

a_Output[index].x = a_Direction[index].x * 0.5f + 0.5f;
a_Output[index].y = a_Direction[index].y * 0.5f + 0.5f;
a_Output[index].z = a_Direction[index].z * 0.5f + 0.5f;

这句话就足够了(不需要为每个元素写一行):

a_Output[index] = a_Direction[index] * 0.5f + 0.5f;