6

我以为我在某个地方读到过,(尽管我终其一生都找不到源代码),即使用 C++ API,您不必像使用 C API 那样释放设备/内核/内存cl::Kernel、cl::Buffer、cl::Device 的析构函数在类对象超出范围时执行此操作(程序结束等)。但是,在仔细检查 cl.hpp(最新版本,1.1 rev 04)后,我根本看不到任何析构函数的定义。例如,这里是 cl::Device -

/*! \class Device
 * \brief Device interface for cl_device_id.
 */
class Device : public detail::Wrapper<cl_device_id>
{
public:
    Device(cl_device_id device) { object_ = device; }

    Device() : detail::Wrapper<cl_type>() { }

    Device(const Device& device) : detail::Wrapper<cl_type>(device) { }

    Device& operator = (const Device& rhs)
    {
        if (this != &rhs) {
            detail::Wrapper<cl_type>::operator=(rhs);
        }
        return *this;
    }

    template <typename T>
    cl_int getInfo(cl_device_info name, T* param) const
    {
        return detail::errHandler(
            detail::getInfo(&::clGetDeviceInfo, object_, name, param),
            __GET_DEVICE_INFO_ERR);
    }

    template <cl_int name> typename
    detail::param_traits<detail::cl_device_info, name>::param_type
    getInfo(cl_int* err = NULL) const
    {
        typename detail::param_traits<
            detail::cl_device_info, name>::param_type param;
        cl_int result = getInfo(name, &param);
        if (err != NULL) {
            *err = result;
        }
        return param;
    }

#if defined(USE_CL_DEVICE_FISSION)
    cl_int createSubDevices(
        const cl_device_partition_property_ext * properties,
        VECTOR_CLASS<Device>* devices)
    {
        typedef CL_API_ENTRY cl_int 
            ( CL_API_CALL * PFN_clCreateSubDevicesEXT)(
                cl_device_id /*in_device*/,
                const cl_device_partition_property_ext * /* properties */,
                cl_uint /*num_entries*/,
                cl_device_id * /*out_devices*/,
                cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;

        static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL;
        __INIT_CL_EXT_FCN_PTR(clCreateSubDevicesEXT);

        cl_uint n = 0;
        cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n);
        if (err != CL_SUCCESS) {
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
        }

        cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id));
        err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids, NULL);
        if (err != CL_SUCCESS) {
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
        }

        devices->assign(&ids[0], &ids[n]);
        return CL_SUCCESS;
    }
#endif
};

有人对这个有了解吗?我应该关心这个吗?在 C++ 包装器文档中,他们甚至没有提到任何类似于 releaseClMemObject 或 free(cl_devices) 等的东西。

谢谢。

4

3 回答 3

12

如果您进一步观察,您会发现所有这些类都继承自模板detail::Wrapper<T>,而这些类又专门针对每种类型clRelease...在其析构函数中调用相应的函数,如您所知,类的析构函数将始终调用其基类类析构函数,因此不需要用户定义的析构函数cl::Buffercl::Kernel和朋友。(好吧,正确地说,Wrapper<T>它不是专门的,而是使用了一些其他专门的特征类来命名ReferenceHandler<T>,它带来了retainrelease功能。)

因此,由于所有这些 OpenCL 对象都使用某种引用计数语义,并且所有这些 C++ 包装器都将相应的clRetain/clRelease调用包装在它们的构造函数和析构函数中,因此您确实不必担心在使用 C++ 时正确释放 OpenCL 资源,只需 RAII 方式它应该是。

(但就像DarkZeros已经说过的那样,设备可能是一个坏例子,因为设备通常不会被保留或释放(并且detail::Wrapper<cl_device_id>' 的 con/destructor 可能什么都不做)。使用 OpenCL 1.2 的设备裂变,它们可能会,但 C++ wrapper 无论如何都不支持 1.2。)

于 2013-06-24T12:20:03.547 回答
4

在 OpenCL 中唯一需要发布的是抽象结构。喜欢:

  • 内存对象
  • 上下文
  • 命令队列
  • 程式
  • 内核
  • 活动

您不能释放设备,因为设备不能被“销毁”或取消分配。当您调用 getDevice 时,您会收到设备的 ID,而不是新创建的设备。

注意:在 OCL 1.2 中,可以将设备构造为上层设备(子设备)的分区。所以,它应该有一个删除案例。也许 CL API 应该处理新版本的这种特殊情况......我不知道

于 2013-06-24T12:03:30.257 回答
1

只需使用

clReleaseMemObject(your_buffer());

使用 cl::Buffer 或其他类时,秘密()在 your_buffer 名称之后。使用与其他相同的逻辑/语法。

于 2019-02-07T02:14:07.847 回答