clRetainMemObject

Hi all

About clRetainMemObject I read in the OpenCL specification:

“After the memobj reference count becomes zero and commands queued for execution on a command-queue(s) that use memobj have finished, the memory object is deleted.”

What does it mean exactly? I mean, It thought that clReleaseMemObject release the space needed by the object memory. Maybe I’m wrong. Which is the difference between both?

Thank you.

I love this question :slight_smile:

Let’s explain what happens with an example. This is a very silly piece of code but it will show what OpenCL does:


// Create a buffer called 'taco'
cl_mem taco = clCreateBuffer(...);

// Enqueue some nonblocking command that accesses 'taco'
clEnqueueWriteBuffer(..., CL_FALSE, ... , taco, ...);

// Release 'taco'
clReleaseMemObject(taco);

// Is taco still alive here?

The answer to that last question is: maybe. Imagine for a moment that calling clReleaseMemObject() immediately deleted ‘taco’ and all resources associated with it. Would OpenCL work correctly? No, it wouldn’t! Why? Because clEnqueueWriteBuffer() is an asynchronous operation and the OpenCL device may still try to read or write to the data stored in ‘taco’.

This is why OpenCL drivers keep track of these things and keep objects alive until it is safe to delete them for good. However, from the application’s point of view, ‘taco’ is already released, so the app cannot enqueue any more operations that access it.

So, correct me if I’m wrong. Using the same example:


// Create a buffer called 'taco'
cl_mem taco = clCreateBuffer(...);

// Enqueue some nonblocking command that accesses 'taco'
clEnqueueWriteBuffer(..., CL_FALSE, ... , taco, ...);

// Release 'taco'
clReleaseMemObject(taco);

// Is taco still alive here? Maybe but it can't be enqueued anymore

But,


// Create a buffer called 'taco'
cl_mem taco = clCreateBuffer(...);

// Enqueue some nonblocking command that accesses 'taco'
clEnqueueWriteBuffer(..., CL_FALSE, ... , taco, ...);

// Release 'taco'
clRetainMemObject(taco);

/* Is taco still alive here? No at all because it will wait until "the memobj reference count becomes zero and commands queued for execution on a command-queue(s) that use memobj have finished. And of course it can't be enqueued anymore.*/

// Is taco still alive here? Maybe but it can’t be enqueued anymore

That is correct.

Let’s look at the new example you provided:


// Create a buffer called 'taco'
cl_mem taco = clCreateBuffer(...);

// Enqueue some nonblocking command that accesses 'taco'
clEnqueueWriteBuffer(..., CL_FALSE, ... , taco, ...);

// Release 'taco'
clRetainMemObject(taco);

/* Is taco still alive here? No at all because it will wait until "the memobj reference count becomes zero and commands queued for execution on a command-queue(s) that use memobj have finished. And of course it can't be enqueued anymore.*/

Taco is definitely alive after that retain. A retain will increase its reference count from 1 to 2. It can also be used to enqueue new commands. It doesn’t even matter whether previous commands using that memory object have finished or not. A retain ensures that the reference count is not zero.

Sorry, I did not understand you. Now is clear.

My last question is, why is this usefull? I mean, to ensure that the reference count is not zero don’t call clReleaseMemObject. Does it mean that if clReleaseMemObject is called over and object memory which has been previously called with clRetainMemObject is not released?

Thank you.

My last question is, why is this usefull? I mean, to ensure that the reference count is not zero don’t call clReleaseMemObject. Does it mean that if clReleaseMemObject is called over and object memory which has been previously called with clRetainMemObject is not released?

Right, if you call clRetainMemObject() once and then you call clReleaseMemObject() the object will not be destroyed – because you would need one more call to clReleaseMemObject().

This is very useful to develop libraries or complex applications that use OpenCL: you can pass OpenCL objects around. Every time a class or module receives a reference to a new object it will simply do a Retain(), and when the class/module is finished with the object it will do a Release(). That way the OpenCL object will be destroyed when nobody is using it anymore.

It’s essentially the same way that managed languages like Java or Python handle objects.

Brilliant!! Thank you very much for your answers.

Thank you for the answer/solution! I’m glad it’s been posted… 8)

Ab