我有两个内核(它们都只运行一次,因此示例中的globalWorkSize为1):
第一个内核(kernel_Calc()
)计算一些值并将它们存储在__global
内存中。在此示例中,它计算(设置转换矩阵,用于转换3D空间中的点)转换矩阵并转换原点。
inline
float4 mul( const float4 M[ 4 ], const float4 v)
{
float4 r;
r.x = dot( v, M[ 0 ] );
r.y = dot( v, M[ 1 ] );
r.z = dot( v, M[ 2 ] );
r.w = dot( v, M[ 3 ] );
return r;
}
__kernel
void kernel_Calc( __global float4* g_TransformationMatrices, __global float3* g_Point3D )
{
__private float4 transformationMatrix[ 4 ];
transformationMatrix [ 0 ] = (float4) ( 1.0f, 0.0f, 0.0f, 0.0f );
transformationMatrix [ 1 ] = (float4) ( 0.0f, 1.0f, 0.0f, 10.0f );
transformationMatrix [ 2 ] = (float4) ( 0.0f, 0.0f, 1.0f, 0.0f );
transformationMatrix [ 3 ] = (float4) ( 0.0f, 0.0f, 0.0f, 1.0f );
g_TransformationMatrices[ 0 ] = transformationMatrix[ 0 ];
g_TransformationMatrices[ 1 ] = transformationMatrix[ 1 ];
g_TransformationMatrices[ 2 ] = transformationMatrix[ 2 ];
g_TransformationMatrices[ 3 ] = transformationMatrix[ 3 ];
float4 point4D = (float4) ( 0.0f, 0.0f, 0.0f, 1.0f );
float4 point4DTransformed = mul( transformationMatrix, point4D);
g_Point3D[ 0 ] = (float3) ( point4DTransformed.x / point4DTransformed.w ,
point4DTransformed.y / point4DTransformed.w ,
point4DTransformed.z / point4DTransformed.w );
}
在主机端,我将计算出的__global
缓冲区复制到具有__constant
功能的CL_MEM_READ_ONLY
缓冲区(clEnqueueCopyBuffer()
缓冲区)中。 (我之所以这样做是因为我希望从__constant
内存中读取的内容比从__global
内存中读取的内容要快。缓冲区副本可以在设备端使用此功能完成,而无需复制{{1} }返回主机,然后将其复制到__global
。)
第二个内核(__constant
)尝试将计算出的值加载到kernel_Test()
变量(__global
)中,该变量可以在主机端读取。 __global float4* test
是用户定义的结构,它只包含一个整数(这是矩阵和变换点的数量)。第二个和第三个参数是sizeStruct
内存中填充了__constant
函数的缓冲区。
clEnqueueCopyBuffer()
问题是当我运行程序时,测试变量包含:
struct sizeStruct
{
int m_Size;
};
__kernel
void kernel_Test( __constant struct sizeStruct* c_SS,
__constant float4* c_TransformationMatrices,
__constant float3* c_Points3D,
__global float4 *test )
{
test[ 0 ] = c_TransformationMatrices[ 0 ];
test[ 1 ] = c_TransformationMatrices[ 1 ];
test[ 2 ] = c_TransformationMatrices[ 2 ];
test[ 3 ] = c_TransformationMatrices[ 3 ];
}
但它应该包含:
1.000000, 0.000000, 0.000000, 0.000000
0.000000, 0.000000, 0.000000, 0.000000
0.000000, 0.000000, 0.000000, 0.000000
0.000000, 0.000000, 0.000000, 0.000000
我检查了1.000000, 0.000000, 0.000000, 0.000000
0.000000, 1.000000, 0.000000, 10.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
变量(通过将它们复制到主机内存中),它们包含正确的数据。代码是我程序的简化版本。这就是它可能包含不必要的操作和参数的原因。该示例已经过测试,可以按照我的描述进行操作。
当我将__constant
内核参数更改为__constant float3* c_Points3D
内核参数(但仍然使用填充了__global float3* c_Points3D
函数的read_only缓冲区)时更有趣,它工作正常。当我删除clEnqueueCopyBuffer()
参数时,它也有效。
所以看起来kernel_Test参数的地址空间有问题,但问题出现在__constant struct sizeStruct* c_SS
- > __constant
副本。
我在nvidia geforce gtx 690上运行该程序,但我可以将设备(和平台)更改为intel i7-3930k(使用intel sdk)。使用intel-i7 cpu一切正常,内核代码没有任何变化。
Q1:为什么会出现这种奇怪的行为?有没有人知道我做错了什么?
Q2:使用__global
创建缓冲区并使用cl_mem_read_only
地址空间限定符是否合法?
答案 0 :(得分:0)
Q1 :为什么会出现这种奇怪的行为?有没有人知道我做错了什么?
没有任何明显的想法,你能发布一个在Windows上编译的完整的最小工作示例吗?我想测试AMD Radeon GPU。
Q2:使用cl_mem_read_only创建缓冲区并使用__global地址空间限定符是否合法?
是的,这是合法的,尽管您需要添加const
来指定缓冲区是只读的,请参阅OpenCL 1.2规范的第6.5.1节。