Opencl:从_常量复制到_全局内存
我有两个内核(它们都只运行一次,因此示例中globalWorkSize为1): 第一个内核(Opencl:从_常量复制到_全局内存,opencl,intel,nvidia,Opencl,Intel,Nvidia,我有两个内核(它们都只运行一次,因此示例中globalWorkSize为1): 第一个内核(kernel\u Calc())计算一些值并将它们存储在\u全局内存中。在本例中,它计算(设置转换矩阵,转换三维空间中的点)转换矩阵并转换origo inline float4 mul( const float4 M[ 4 ], const float4 v) { float4 r; r.x = dot( v, M[ 0 ] ); r.y = dot( v, M[ 1 ] );
kernel\u Calc()
)计算一些值并将它们存储在\u全局
内存中。在本例中,它计算(设置转换矩阵,转换三维空间中的点)转换矩阵并转换origo
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 );
}
在主机端,我使用clEnqueueCopyBuffer()
函数将计算出的\uuuu全局
缓冲区复制到\uu常量
缓冲区(CL\u MEM\u只读
缓冲区)。(我这样做是因为我希望从\uuu常量
内存读取的速度比从\uu全局
内存读取的速度快。使用此功能可以在设备端完成缓冲区复制,而无需将\uu全局
复制回主机,然后将其复制到\uu常量
)
第二个内核(kernel\u Test()
)尝试将计算出的值加载到可在主机端读取的\uuu global
变量(\uu global float4*Test
)中。sizeStruct
是一个用户定义的结构,它只包含一个整数(这是矩阵和转换点的数目)。第二个和第三个参数是\u常量
内存中的缓冲区,这些缓冲区被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
我检查了\u常量
变量(通过将它们复制到主机内存),它们包含正确的数据。代码是我程序的简化版本。这就是它可能包含不必要的操作和参数的原因。这个例子已经过测试,并按照我所描述的那样工作
更有趣的是,当我将\uuu常量float3*c_Points3D
内核参数更改为\uu全局float3*c_Points3D
内核参数时(但仍然使用用clEnqueueCopyBuffer()函数填充的只读缓冲区),它工作得很好。当我删除\u常量struct sizeStruct*c\u SS
参数时,它也会起作用。
因此,内核测试的参数的地址空间似乎有问题,但问题出现在\uu常量
->\uu全局
copy
我正在nvidia geforce gtx 690上运行该程序,但我可以将设备(和平台)更改为intel i7-3930k(使用intel sdk)。使用intel-i7 cpu,一切正常,内核代码没有任何更改
Q1:为什么会出现这种奇怪的行为?有人知道我做错了什么吗
Q2:使用cl\u mem\u read\u
创建缓冲区并与\u global
地址空间限定符一起使用是否合法
Q1:为什么会出现这种奇怪的行为?有人知道我做错了什么吗
我想不出什么明显的问题,你能给出一个在Windows上编译的完整的最低限度的工作示例吗?我想在AMD Radeon GPU上测试
Q2:使用cl\u mem\u read\u创建缓冲区并与\u全局地址空间限定符一起使用是否合法
是的,这是合法的,尽管您需要添加const
以指定缓冲区为只读,请参阅OpenCL 1.2规范的第6.5.1节。谢谢您的回答。我在这里上传了测试项目(VS2010):您的代码在我的AMD Radeon HD 6970上正常工作。稍后我将测试一些Nvidia卡。Nvidia卡在OpenCL中对向量的支持非常糟糕,float4可能是问题的根本原因。AMDs FFT实现也会发生同样的情况,它们使用float2,代码在Intel CPU和AMD GPU上运行良好,但在NVIDIA卡上运行不好。