我有两个内核(它们都只运行一次,因此示例中的 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
。缓冲区复制可以在设备端使用此功能完成,而无需复制__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
内核参数(但仍使用已填充clEnqueueCopyBuffer()
函数的 read_only 缓冲区)时,它工作正常。__constant struct sizeStruct* c_SS
当我删除参数时它也有效。因此,kernel_Test 参数的地址空间似乎有问题,但问题出现在__constant
->__global
复制。
我在 nvidia geforce gtx 690 上运行程序,但我可以将设备(和平台)更改为 intel i7-3930k(使用 intel sdk)。使用 intel-i7 cpu 一切正常,内核代码没有任何变化。
Q1:为什么会出现这种奇怪的行为?有人知道我在做什么错吗?
Q2:使用地址空间限定符创建缓冲区cl_mem_read_only
和使用 with是否合法?__global