Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Releasing Opencl Memory, Kernels, Devices etc

Tags:

c++

opencl

I thought I read somewhere, (though, for the life of me, I can't find the source), that, using the C++ API you don't have to release devices/kernels/memory like w/ the C API as the destructors for cl::Kernel, cl::Buffer, cl::Device do this when the class objects go out of scope, (end of program, etc). However, upon closer examination of cl.hpp (the latest one, 1.1 rev 04), I don't see any destructors defined at all. For example, here is 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
};

Does anyone know anything about this? Should I care about this? In the C++ wrapper documentation they do not even mention anything resembling releaseClMemObject or free(cl_devices), etc.

Thanks.

like image 625
Steve Novakov Avatar asked Jun 22 '13 01:06

Steve Novakov


2 Answers

If you look further, then you will see that all those classes inherit from a template detail::Wrapper<T> and that in turn is specialized for each and every type to indeed call the corresponding clRelease... function in its destructor and as you know, a class's destructor will always call its base class destructors, so there is no need for a user-defined destructor in cl::Buffer, cl::Kernel and friends. (Well, to be correct Wrapper<T> is not specialized but uses some other specialized traits class named ReferenceHandler<T> that brings the retain and release functions.)

So since all those OpenCL objects use some kind of reference counting semantics and all those C++ wrappers wrap the corresponding clRetain/clRelease calls in their constructors and destructors, you indeed don't have to worry about properly releasing OpenCL resources when working with C++, just RAII the way it should be.

(But like already said by DarkZeros, a device is probably a bad example, since devices are usually not retained or released (and detail::Wrapper<cl_device_id>'s con/destructor will probably do nothing). With OpenCL 1.2's device fission they may, but the C++ wrapper doesn't support 1.2 anyway.)

like image 174
Christian Rau Avatar answered Oct 25 '22 17:10

Christian Rau


The only things that need a release in OpenCL are the abstract constructions. Like:

  • Memory objects
  • Contexts
  • Command Queues
  • Programs
  • Kernels
  • Events

You cannot release a device, since a device cannot be "destroyed" or un-allocated. When you call getDevice you receive an ID to the device, not a new created device.

NOTE: In OCL 1.2 a device can be constructed as a partition of an upper device (subdevice). So, it should have a delete case. Maybe the CL API should take care of this specific case of the new verisons... I dunno

like image 20
DarkZeros Avatar answered Oct 25 '22 17:10

DarkZeros