首页 > 解决方案 > 如何使用 OpenCL C++ 绑定获得最大的全局工作大小?

问题描述

我想获得最大的全球工作规模。我不希望内核 OpenCL 会尝试为您选择最好的内核,这可能是也可能不是最大尺寸。

为此,我想在调用时指定大小clEnqueueNDRangeKernel。例如:

clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size, NULL, 0, NULL, NULL);

clGetKernelWorkGroupInfo 文档,指出:

CL_KERNEL_GLOBAL_WORK_SIZE :这为应用程序提供了一种机制来查询可用于在 device 给出的自定义设备上执行内核的最大全局大小(即 clEnqueueNDRangeKernel 的 global_work_size 参数)或由 device 给出的 OpenCL 设备上的内置内核.

如何CL_KERNEL_GLOBAL_WORK_SIZE使用 OpenCL C++ 绑定?

我这样做

cl::array<size_t, 3> kernel_global_work_size = my_kernel.getWorkGroupInfo<CL_KERNEL_GLOBAL_WORK_SIZE>(my_device);

但我得到了错误:

cl2.hpp:5771:12: note: candidate: template<class T> cl_int cl::Kernel::getWorkGroupInfo(const cl::Device&, cl_kernel_work_group_info, T*) const
     cl_int getWorkGroupInfo(
            ^~~~~~~~~~~~~~~~
cl2.hpp:5771:12: note:   template argument deduction/substitution failed:
cl2.hpp:5782:9: note: candidate: template<int name> typename cl::detail::param_traits<cl::detail::cl_kernel_work_group_info, name>::param_type cl::Kernel::getWorkGroupInfo(const cl::Device&, cl_int*) const
         getWorkGroupInfo(const Device& device, cl_int* err = NULL) const

并使用此代码

cl::array<size_t, 3> kernel_global_work_size;
my_kernel.getWorkGroupInfo<cl::array<size_t, 3>>(my_device, CL_KERNEL_GLOBAL_WORK_SIZE, &kernel_global_work_size);

我收到 OpenCL 错误 -30(无效值)

my_kernel不是内置内核,例如:cl::Kernel my_kernel = cl::Kernel(program, "my_kernel"); my_device不是自定义设备。例如:cl::Device device = myDevices[0];

标签: c++opencl

解决方案


是的,因为您的电话与签名匹配:

https://github.khronos.org/OpenCL-CLHPP/classcl_1_1_kernel.html

template <cl_int name> typename
detail::param_traits<detail::cl_kernel_work_group_info, name>::param_type getWorkGroupInfo(const Device& device, cl_int* err = NULL) const;

看起来param_traits通过宏生成的 没有为CL_KERNEL_GLOBAL_WORK_SIZE. 那将是标题中的错误。(由 OP 创建的 GitHub 问题

对于此处的某些条目 此处 缺少条目 。

或者,您可以使用返回错误代码的版本以及通过输出参数提供的信息,这应该可以解决该问题:

template<typename T>
cl_int getWorkGroupInfo(const Device &device, cl_kernel_work_group_info name, T *param) const;

调用可能如下所示:

cl::array<size_t, 3> result;
kernel.getWorkGroupInfo<decltype(result)>(device, CL_KERNEL_GLOBAL_WORK_SIZE, result);

我的问题是:你自己试过吗?结果不符合您的期望吗?


您收到 CL_INVALID_VALUE 了吗?

[...] 在设备给定的自定义设备上或在设备给定的 OpenCL 设备上的内置内核上。

如果 device 不是自定义设备或内核不是内置内核,则 clGetKernelArgInfo 返回错误 CL_INVALID_VALUE。

请参阅OpenCL 1.2 规范,第 14 和 15 页:

内置内核:内置内核是通过固定功能硬件或固件在 OpenCL 设备或定制设备上执行的内核。应用程序可以查询设备或自定义设备支持的内置内核。程序对象只能包含用 OpenCL C 编写的内核或内置内核,但不能同时包含两者。另请参见内核和程序。

定制设备:完全实现 OpenCL 运行时但不支持用 OpenCL C 编写的程序的 OpenCL 设备。定制设备可能是专门的非可编程硬件,它对于定向任务或具有有限可编程能力的硬件非常节能和高性能,例如专门的 DSP。自定义设备不符合 OpenCL。定制设备可能支持在线编译器。可以使用 OpenCL 运行时 API 创建自定义设备的程序,这些 API 允许从源代码(如果支持在线编译器)和/或二进制文件或设备支持的内置内核创建 OpenCL 程序。另见设备。

对于常规内核和设备,标准限制了工作组大小(设备属性),而全局大小仅受使用的范围限制size_t。请参阅clEnqueueNDRangeKernel


推荐阅读