How to retain a CLBuffer possibly calling clRetainMemObject

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

How to retain a CLBuffer possibly calling clRetainMemObject

Andrew Bailey
Hi,

I want to execute 2 kernels the second one processing a CLBuffer generated by the first, however it appears that using the high level jocl api that the buffers are being released automatically.

There is a method CLBuffer.release() however retain() does not appear.

I have looked for a way of calling the low level cl_int clRetainMemObject (cl_mem memobj)
using a class such as org.jocl.utils.Mems however there are only methods to create and release org.jocl.cl_mem.

The only way I have managed to get the program to work so far is by copying the buffer to host memory and creating a new buffer and copying the data back, I would like to avoid this.

Is there another way of implementing the desired funcionality?

Is there any reason why retain() is not implemented in CLBuffer?

Thanks in advance
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Wade Walker
Administrator
Let me take a look at this. I'm working on another bug right now, but hopefully it'll be finished tonight. It would help if you open an enhancement request for this on our Bugzilla and five an example of how you think it should work.
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Andrew Bailey
I tried twice to create a bugzilla account but still no email. So no bug report ...

I also tried to recreate a small test case for the problem that I saw earlier, but the buffers were not released automatically as I saw before.
Could it be to do with the size of the dataset?

In any case the proposed method is CLBuffer.retain();

Here is a fragment of how it could be used:

CLProgram program = context.createProgram(Resize.class.getResourceAsStream("/kernels.cl")).build();

                        CLKernel kernel1 = program.createCLKernel("kernel1");
                        CLKernel kernel2 = program.createCLKernel("kernel2");

                        CLCommandQueue queue = device.createCommandQueue();
                        try {
                                CLBuffer<IntBuffer> clBuffer = context.createIntBuffer(samples.length, Mem.READ_WRITE);
                                clBuffer.registerDestructorCallback(new DebugRelease("clBuffer"));

                                CLBuffer<IntBuffer> clBufferResult = context.createIntBuffer(samples.length, Mem.READ_WRITE);
                                clBufferResult.registerDestructorCallback(new DebugRelease("clBufferResult"));

                                clBuffer.getBuffer().put(samples).flip();

                               
                                try {
                                        // I would expect the following to be possible calling
                                        // clRetainMemObject on
                                        //clBuffer.retain();

                                        queue.putWriteBuffer(clBuffer, true);
                                       

                                        kernel1.rewind().putArg(clBuffer).putArg(clBufferResult).putArg(samples.length);
                                        globalWidth=samples.length;
                                        queue.put1DRangeKernel(kernel1, 0, globalWidth, workGroupWidth);
                                        queue.putReadBuffer(clBufferResult, true);
                                       
                                        //Ideally this line should not be needed
                                        queue.putReadBuffer(clBuffer, true);

                                        IntBuffer intBuffer = clBufferResult.getBuffer();

                                        // ....process results from first kernel
                                       
                                        clBufferResult.release();
                                       
                                        //Ideally this line should not be needed
                                        //clBuffer.release();
                                       
                                        //ShortBuffer tempBuffer = (ShortBuffer) clBuffer.getBuffer().rewind();
                                        //clBuffer = context.createShortBuffer(samples.length, Mem.READ_WRITE);
                                        //clBuffer.getBuffer().put(tempBuffer).rewind();
                                        //queue.putWriteBuffer(clBuffer, true);

                                        //... do work on host here
                                       
                                        kernel2.rewind().putArg(clBuffer).putArg(samples.length);
                                        queue.put1DRangeKernel(kernel2, 0, globalWidth, workGroupWidth);
                                        queue.putReadBuffer(clBuffer, true);

                                        // ...use result
                                } finally {
                                        //release the buffer we retained earlier
                                        clBuffer.release();
                                }
                        } finally {
                                queue.release();
                        }
                } finally {
                        context.release();
                }
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Wade Walker
Administrator
Weird, not sure what's up with Bugzilla -- I'll create a report and add you as a CC. My previous bug has ballooned out into an unexpected mess, but hopefully I can look at this one over the weekend.
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Wade Walker
Administrator
In reply to this post by Andrew Bailey
I created an enhancement request at https://jogamp.org/bugzilla/show_bug.cgi?id=1303. You can register your email address on it as a CC to get notified of changes.

I can't see any reason why this wasn't included in the original release, since clRetainMemObject() has been around since OpenCL 1.0. Maybe the original author just didn't think of it :)
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Andrew Bailey
Great thanks.

Wade, I imagine you have though of this, but just in case, I was wondering what should happen to the following method when retain is implemented:

public abstract class  ...CLMemory  extends CLObjectResource {

  @Override
224    public void  ...release() {
225        super.release();
226        final int ret = binding.clReleaseMemObject(ID);
227        context.onMemoryReleased(this);
228        if(ret != CL_SUCCESS) {
229            throw newException(ret, "can not release "+this);
230        }
231    }
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Wade Walker
Administrator
I imagine that when you retain an object, that would set a flag that would prevent its automatic release afterwards. So then the user will have to call the release method manually once they're know they're finished with the object. I'll need to set up your use-case as a unit test and see what it looks like, though.
Reply | Threaded
Open this post in threaded view
|

Re: How to retain a CLBuffer possibly calling clRetainMemObject

Wade Walker
Administrator
In reply to this post by Andrew Bailey
I looked into this, and it appears that the auto-release of buffers is a byproduct of creating the buffers with CLContext.createBuffer*(). They're added to a list inside CLContext, and released in CLContext.release() (which calls CLBuffer.release()). Or if you call CLBuffer.release() yourself, the buffer removes itself from the context's internal list.

CLBuffers may also be released by the Java AutoCloseable interface if you use them with a try-with-resources pattern (see https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html).

So if you don't release the context or the buffers yourself, and you're not using try-with-resources, the buffers shouldn't be getting released. Do you have some indication that they're being released somehow? Maybe I'm missing something, but it seems like what you want to do should already work, without requiring any calls to clRetainMemObject() :)