Opencl 乔:为什么要使用缓冲区?

Opencl 乔:为什么要使用缓冲区?,opencl,Opencl,给定要传递给OpenCL内核的float[n]inputdata,有人能告诉我以下三种传递给内核的方法的区别吗: (A) (B) (C) ? 我是否正确理解了A)和C)之间的区别是C)在开始时复制整个阵列一次,然后使用它在GPU上工作,而A)必须动态加载其数据?因此,A)如果只需要阵列的一小部分,则是好的;C)如果使用整个阵列,则是好的方法 B呢?它更像A)、更像C),还是仍然有些不同?是的,不能传递大量参数。所有参数的大小都有一个上限(通常在50 KiB的范围内——您可以使用clGetDevi

给定要传递给OpenCL内核的
float[n]inputdata
,有人能告诉我以下三种传递给内核的方法的区别吗:

(A)

(B)

(C)

?

我是否正确理解了A)和C)之间的区别是C)在开始时复制整个阵列一次,然后使用它在GPU上工作,而A)必须动态加载其数据?因此,A)如果只需要阵列的一小部分,则是好的;C)如果使用整个阵列,则是好的方法


B呢?它更像A)、更像C),还是仍然有些不同?

是的,不能传递大量参数。所有参数的大小都有一个上限(通常在50 KiB的范围内——您可以使用
clGetDeviceInfo
CL\u设备\u最大参数\u大小查询它)。使用方法a和c,您可以传递更大的缓冲区(数百兆字节)。a对OpenCL 1.1和更低版本没有帮助,因为缓冲区通常仍会被复制,但使用OpenCL 1.2,如果您的主机和设备相同(例如,您正在运行CPU OpenCL运行时),则可以避免一次复制。

每个方法的作用:

A) 此方法使用主机的缓冲区存储数据。当您不想将数据复制到设备,但想就地使用时。我相信这只可能在CPU设备上实现,但我不能完全确定

B) 将_global*类型传递给内核。对有限数量的数据使用此选项。请注意,对于此文件的_local/NULL版本,大量工作项/组可能会对性能产生很大(负面)影响。大小限制为CL_设备\u最大\u参数\u大小。传递NULL将导致uu local*类型,限制为CL_DEVICE_local_MEM_SIZE


C) 当您的内核需要大量(即超过方法B的限制)数据时,请使用此选项。这会将数据从主机的缓冲区复制到设备的缓冲区。如果您的数据已准备好使用,您可以在创建CL_mem buffer时使用mem标志CL_mem_COPY_HOST_PTR进行复制,并跳过clEnqueueWriteBuffer调用。

您能否为B)自动将变量作为_local传递的说法提供参考?这听起来很奇怪,因为非数组变量似乎不是这样。如果将null作为指针传递,并且只传递大小,则指定本地缓冲区的大小(指针必须为null,因此无法在内核调用时将数据分配和复制到本地缓冲区中。)我的错误是,它必须为null才能为u local。在这种情况下,您将受到CL_设备\本地\内存\大小的约束。否则,它是全局的,限制为CL_设备_最大_参数_大小。只想在A上展开);当OpenCL设备共享RAM时(就像在集成GPU中经常做的那样),这是有意义的那么大小限制是唯一的区别?例如,只要B)有效,就没有理由使用A)或C)?它会比A)和C)更快还是更慢(例如,当主机更改数组内容时),或者它们真的是等价的?语义和大小。如果是某个缓冲区,则应使用缓冲区,因为最大参数大小可能小到256字节(!)。小心海报mfa,他错了,因为你不能轻易地将数据传递到本地;您只能在内核调用时设置_本地缓冲区的大小(您仍然需要将数据复制到_本地)。如果您只需要将数据获取到GPU上,我会使用。
cl_mem input = clCreateBuffer(context, CL_MEM_USE_HOST_PTR Sizeof.cl_float * n,
        inputdata, NULL);
clSetKernelArg(kernel, i, Sizeof.cl_mem, Pointer.to(input));
clSetKernelArg(kernel, i, Sizeof.cl_float * n, Pointer.to(inputdata));
cl_mem input = clCreateBuffer(context, CL_MEM_options_here, Sizeof.cl_float * n,
        NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, Sizeof.cl_float * n, 
        inputdata, 0, NULL, NULL);
clSetKernelArg(kernel, i, Sizeof.cl_mem, Pointer.to(input));