今天__local
,我在内核中添加了四个变量来转储中间结果。但是,只需将这四个变量添加到内核的签名中并添加相应的内核参数,内核的所有输出就会变为“0”。没有一个 cl 函数返回错误代码。
我进一步尝试只添加两个较小的变量之一。如果我只添加其中一个,它可以工作,但如果我同时添加它们,它就会崩溃。
那么 OpenCL 的这种行为是否意味着我分配了很多__local
内存?我如何知道我可以使用多少__local
内存?
今天__local
,我在内核中添加了四个变量来转储中间结果。但是,只需将这四个变量添加到内核的签名中并添加相应的内核参数,内核的所有输出就会变为“0”。没有一个 cl 函数返回错误代码。
我进一步尝试只添加两个较小的变量之一。如果我只添加其中一个,它可以工作,但如果我同时添加它们,它就会崩溃。
那么 OpenCL 的这种行为是否意味着我分配了很多__local
内存?我如何知道我可以使用多少__local
内存?
可以通过使用带有函数的CL_DEVICE_LOCAL_MEM_SIZE
标志来查询设备在其每个计算单元上提供的本地内存量:clGetDeviceInfo
cl_ulong size;
clGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &size, 0);
返回的大小以字节为单位。每个工作组都可以为自己严格分配这么多内存。但是请注意,如果它确实分配了最大值,这可能会阻止在同一计算单元上同时调度其他工作组。
当然有,因为本地内存是物理的而不是虚拟的。
从在 CPU 上使用虚拟地址空间,我们习惯于在理论上拥有我们想要的尽可能多的内存 - 由于分页文件/交换分区用完,或者甚至可能不会,直到我们实际尝试,可能会在非常大的大小上失败使用过多的内存,使其无法映射到物理 RAM 和磁盘。
对于需要访问实际 RAM 中特定区域的计算机操作系统内核(或它的较低级别部分)等情况,情况并非如此。
GPU 全局和本地内存也不是这种情况。没有*内存分页(感知线程地址到物理内存地址的重新映射);并且没有交换。特别是关于本地内存,每个计算单元(= GPU 上的每个对称多处理器)都有一堆用作本地内存的 RAM;这里的绿色板:
每个这样的板的大小就是你得到的
clGetDeviceInfo( · , CL_DEVICE_LOCAL_MEM_SIZE, · , ·)
.
为了说明,在nVIDIA Kepler GPU 上,本地内存大小为 16 KB 或 48 KB(64 KB 的补充用于缓存对全局内存的访问)。因此,截至今天,GPU 本地内存相对于全局设备内存非常小。
1 - 在以 Pascal 架构开始的 nVIDIA GPU 上,支持分页;但这不是使用设备内存的常见方式。