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 |
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.
|
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(); } |
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.
|
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 :) |
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 } |
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.
|
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() :) |
Free forum by Nabble | Edit this page |