Nvidia GPU上的OpenCL小型恒定内存大小

Nvidia GPU上的OpenCL小型恒定内存大小,opencl,Opencl,我有下面的矩阵乘法代码,为简单起见缩写。我计划使用块大小*块大小的本地内存来保存子矩阵块。在NVIDIA GPU上运行时,我一直在clEnqueueNDRangeKernel中获取错误代码-52。经过一些研究,我发现NVIDIA gpu上的恒定内存大小非常小 主持人: cl::Buffer a_buf{context,cl_MEM_READ_ONLY | cl_MEM_COPY_HOST_PTR,a.bytes(),a.data}; cl::Buffer b_buf{context,cl_MEM

我有下面的矩阵乘法代码,为简单起见缩写。我计划使用
块大小*块大小的本地内存来保存子矩阵块。在NVIDIA GPU上运行时,我一直在
clEnqueueNDRangeKernel
中获取错误代码
-52
。经过一些研究,我发现NVIDIA gpu上的恒定内存大小非常小

主持人:

cl::Buffer a_buf{context,cl_MEM_READ_ONLY | cl_MEM_COPY_HOST_PTR,a.bytes(),a.data};
cl::Buffer b_buf{context,cl_MEM_READ_ONLY | cl_MEM_COPY_HOST_PTR,a.bytes(),bT.data};
cl::Buffer result_buf{context,cl_MEM_READ_WRITE,result.bytes(),nullptr}//用于内存映射
setArg(0,a_buf);
setArg(1,b_buf);
setArg(2,local_size*local_size*sizeof(float),nullptr);
setArg(3,local_size*local_size*sizeof(float),nullptr);
setArg(4,result_buf);
EnqueuenRangeKernel(内核,{0,0},{a.rows,a.rows},{local_size,local_size});
//^offset^全局工作大小^local工作大小
内核:

\uuuuu内核无效矩阵mul(\uuuu常量浮点*a,
__常量浮点*b,//存储原始矩阵数据
__本地浮点数*本地浮点数,
__局部浮点*b_local,//存储工作组的子矩阵块
__全局浮点*结果)
{...}
使用
CL\u DEVICE\u MAX\u CONSTANT\u BUFFER\u SIZE
,我的RX580返回几乎所有可用的VRAM,但我的GTX1650仅返回64KB。当使用
\uuu constant
而不是
\uu global
时,我的RX580确实获得了显著的性能提升我是否做错了什么,或者恰好是这样,我需要准备不同的内核以在AMD和NVIDIA GPU上运行?

编辑:我在github上发现了一个相关问题
所以我改变了
\uu常量浮点*a
->
\uu全局常量浮点*限制a
,它可以工作。

NVIDIA GPU上的常量内存大小确实非常小,只有64KB(我检查了Titan Xp、GTX 960M、RTX 2080 Ti、特斯拉K20c、特斯拉K40m)。在AMD Radeon VII上,14GB的恒定内存大小要大得多。在Intel CPU(i7-8700K,Xeon E5-2680 v2)上,恒定内存大小为128KB。这是一个驱动程序限制,解决方法是使用
global const float*restrict
(和
restrict
用于类型为
float*
)的所有其他内核参数,而不是您已经了解到的
常量float*

如果AMD GPU上的性能有很大的不同,您可以为AMD和NVIDIA GPU使用不同的内核声明。在编译OpenCL代码之前,您可以通过
#ifdef
或在运行时通过
string
串联在它们之间切换;这样,您不必在代码中包含整个内核两次,而只需要包含内核参数声明的行