OpenCL returns INVALID_KERNEL_ARGS 取决于缓冲区的大小

OpenCL returns INVALID_KERNEL_ARGS depending on size of buffer

我在使用 OpenCL 时遇到一个奇怪的问题,我正在为使用大内存缓冲区作为参数的内核调用 clEnqueueNDRangeKernel。对于小于 16384 字节的缓冲区,一切正常。如果我增加缓冲区大小超过它 returns 一个 INVALID_KERNEL_ARGS 错误。据我了解,此错误意味着未设置参数。将参数设置为无效大小或不适合内存的内容应该会触发不同的错误。

有什么想法吗?

更新

@mfa 的回答让我再次查看了设备规格。看起来一个128*128的float数组恰好是64KB,这是卡常量内存的大小。全局内存要大得多,因此使用 __global 而不是 __constant 作为内核参数可以修复它。

但我仍然很困惑:如何调用 const memory every 的内存不足参数?在我看来,当我创建缓冲区时,它还不知道它是用作常量还是全局...有什么方法可以获得更有用的错误消息吗?

查询您的设备 'CL_DEVICE_MAX_PARAMETER_SIZE',我打赌它会是 16384。这个值是 4096 我的英特尔 cpu。

规范定义的最小值是:

  • opencl 1.0 - 256 字节
  • opencl 1.1 - 1024 字节
  • opencl 1.2 - 1024 字节
  • opencl 2.0 - 1024 字节

Read more on the clGetDeviceInfo page.


回复:缓冲区和内存不足错误

当您创建缓冲区时,就知道它可以连接到哪些设备。 clCreateBuffer 采用缓冲区将与之关联的 cl_context,之前对 clCreateContext 的调用采用了与新上下文关联的设备列表。但是缓冲区不是你的问题。

__constant 是您的原始问题。您的设备不允许您使用总计超过 4352 字节的常量参数,而您正试图传递 65536 字节。全局内存没有这么低的限制(默认情况下,GPU 总内存通常为 50%,CPU 为 25%)。除非您尝试将内核参数设置为太大的值,否则内存不足错误不会是 known/triggered。

当常量内存要共享(或复制——这取决于实现)供所有工作组使用时,问题发生在低级别。计算单元中仅保留有限数量的内存用于此用途。在芯片设计者不得不削减 ALU 内核或其他类型的内存以允许更大的恒定内存大小之前,专用于此目的的晶体管数量有限。即使在 opencl 2.0 中,最小值仍然只有 1024 字节。