upcoming semantical change for buffer operations

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

upcoming semantical change for buffer operations

Michael Bien
This post was updated on .
Hello everyone,

we discussed yesterday on the jogamp XMPP channel a semantical change i would like to implement very soon, here is the idea:

all buffer operations expect params like offsets, sizes, ranges etc to be specified as bytes. This is ok but we can do better in my opinion.
CLMemory and its direct subclasses CLBuffer and CLImage support having a optional nio buffer as host-side storage for the device-side buffer. This buffer can be any subclass of java.nio.Buffer, speak FloatBuffer, DoubleBuffer, ByteBuffer etc. The change would make those buffer operations buffer type agnostic. A queue.putReadBufferRect(aCLBufferWithFloatBufferStorage, origin, range, elements) would expect counting in floats (buffer elements) instead of bytes.

example from spec:
http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueReadBufferRect.html
https://jogamp.org/deployment/webstart-next/javadoc/jocl/javadoc/com/jogamp/opencl/CLCommandQueue.html#putReadBufferRect%28com.jogamp.opencl.CLBuffer,%20int,%20int,%20int,%20int,%20int,%20int,%20int,%20int,%20int,%20boolean,%20com.jogamp.opencl.CLEventList,%20com.jogamp.opencl.CLEventList%29

however there would be some implications/issues:
1) in some situations you will have to mix elements with bytes (CL functions with row_pitch, slice_pitch offsets for example, see spec link above)
2) in other cases you may have a buffer which is not evenly dividable by element_size, copying the buffer by specifying the size in elements may be problematic

1) is not preventable, however i would see the usage of pitch params as corner case and not what you will have to care about in most applications.
2) this is another corner case but can cause confusion

1) 2) are both without further api change solvable. It is already possible to create multiple views of a single CLBuffer:
https://jogamp.org/deployment/webstart-next/javadoc/jocl/javadoc/com/jogamp/opencl/CLBuffer.html#cloneWith%28T%29
so you could switch to a CLBuffer with ByteBuffer storage or even use both views at the same time to access it once via elements and once via bytes.

This could confuse a bit but i believe only if you deal with one of the corner cases above. (you know make the first 80% easy and the remaining 20% possible :) )

What do you think? go/nogo?
comments appreciated,

best regards,
michael


--
http://michael-bien.com/
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Michael Bien
a more concrete example would look like:
            CLBuffer<FloatBuffer> src = context.createFloatBuffer(preparedNIOBuffer);
            CLBuffer<FloatBuffer> dst = context.createFloatBuffer(preparedNIOBuffer.capacity());
            
            int src_offset = 12; // ignore first 12 floats
            int dst_offset = 0;
            //now
            queue.putCopyBuffer(src, dst, src_offset*SIZEOF_FLOAT, dst_offset, (src.capacity()-src_offset)*SIZEOF_FLOAT);
            
            //after the change
            queue.putCopyBuffer(src, dst, src_offset, dst_offset, src.capacity()-src_offset);

            queue.finish();


-michael
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Wade Walker
Administrator
In reply to this post by Michael Bien
Your proposed change does seem to make the use-case simpler in many situations.

The only drawback I can think of is it would make your method parameters have different meanings than those in the spec. So you'd have to put in parameter docs to clearly say which ones are in elements and which ones are in bytes. Right now you don't need parameter docs, since the user can just read the ones in the spec
jdp
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

jdp
In reply to this post by Michael Bien
Yes, definitely.  Coords and dims related to a typed element need to count elements rather than bytes.  
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Sven Gothel
Administrator
In reply to this post by Michael Bien
On Thursday, February 17, 2011 21:30:07 Michael Bien [via jogamp] wrote:

>
> a more concrete example would look like:
>
>             CLBuffer<FloatBuffer> src =
> context.createFloatBuffer(preparedNIOBuffer);
>             CLBuffer<FloatBuffer> dst =
> context.createFloatBuffer(preparedNIOBuffer.capacity());
>            
>             int src_offset = 12; // ignore first 12 floats
>             int dst_offset = 0;
>             //now
>             queue.putCopyBuffer(src, dst, src_offset*SIZEOF_FLOAT,
> dst_offset, (src.capacity()-src_offset)*SIZEOF_FLOAT);
>            
>             //after the change
>             queue.putCopyBuffer(src, dst, src_offset, dst_offset,
> src.capacity()-src_offset);
>
>             queue.finish();
>

yup cool .. and as we discussed, the alignment / row-pitch values in bytes,
if appropriate / exists.

~Sven

>
>
> -michael
>
> _______________________________________________
> If you reply to this email, your message will be added to the discussion below:
> http://forum.jogamp.org/upcoming-semantical-change-for-buffer-operations-tp2519021p2522140.html
> To start a new topic under jocl, email [hidden email]
> To unsubscribe from jocl, visit
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Sven Gothel
Administrator
In reply to this post by Michael Bien
On Saturday, February 19, 2011 17:31:50 Sven Gothel wrote:

> On Thursday, February 17, 2011 21:30:07 Michael Bien [via jogamp] wrote:
> >
> > a more concrete example would look like:
> >
> >             CLBuffer<FloatBuffer> src =
> > context.createFloatBuffer(preparedNIOBuffer);
> >             CLBuffer<FloatBuffer> dst =
> > context.createFloatBuffer(preparedNIOBuffer.capacity());
> >            
> >             int src_offset = 12; // ignore first 12 floats
> >             int dst_offset = 0;
> >             //now
> >             queue.putCopyBuffer(src, dst, src_offset*SIZEOF_FLOAT,
> > dst_offset, (src.capacity()-src_offset)*SIZEOF_FLOAT);
> >            
> >             //after the change
> >             queue.putCopyBuffer(src, dst, src_offset, dst_offset,
> > src.capacity()-src_offset);
> >
> >             queue.finish();
> >
>
> yup cool .. and as we discussed, the alignment / row-pitch values in bytes,
> if appropriate / exists.
>

forgot to nitpick .. IMHO it's more an addition
not a semantical change, since the original method signature will be still available right ?

~Sven
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Michael Bien
On 02/19/2011 05:41 PM, Sven Gothel [via jogamp] wrote:

> On Saturday, February 19, 2011 17:31:50 Sven Gothel wrote:
>
> > On Thursday, February 17, 2011 21:30:07 Michael Bien [via jogamp]
> wrote:
> > >
> > > a more concrete example would look like:
> > >
> > >             CLBuffer<FloatBuffer> src =
> > > context.createFloatBuffer(preparedNIOBuffer);
> > >             CLBuffer<FloatBuffer> dst =
> > > context.createFloatBuffer(preparedNIOBuffer.capacity());
> > >
> > >             int src_offset = 12; // ignore first 12 floats
> > >             int dst_offset = 0;
> > >             //now
> > >             queue.putCopyBuffer(src, dst, src_offset*SIZEOF_FLOAT,
> > > dst_offset, (src.capacity()-src_offset)*SIZEOF_FLOAT);
> > >
> > >             //after the change
> > >             queue.putCopyBuffer(src, dst, src_offset, dst_offset,
> > > src.capacity()-src_offset);
> > >
> > >             queue.finish();
> > >
> >
> > yup cool .. and as we discussed, the alignment / row-pitch values in
> bytes,
> > if appropriate / exists.
> >
>
> forgot to nitpick .. IMHO it's more an addition
> not a semantical change, since the original method signature will be
> still available right ?
>
> ~Sven
>

no. The signature will stay but the meaning will change.
Example signature:
public CLCommandQueue putWriteBuffer(CLBuffer<?> writeBuffer, boolean
blockingWrite){...}
(which is already now at least 4 times overloaded per function signature)

if you put a CLBuffer<FloatBuffer> as writeBuffer it will count 4bytes
as element size, a ByteBuffer as storage would count 1byte per element
accordingly.

I want that change too but first i want to be sure we thought through
all consequences. For example 2) of
http://forum.jogamp.org/upcoming-semantical-change-for-buffer-operations-tp2519021p2519021.html 
could introduce bugs in client code.

example:
CLBuffer<FloatBuffer> over a 9 byte long CL  memory region.

if you naively use the queue.copy(...) methods you will only be able to
copy the first 8bytes since you can not address the 9th byte.

3) There are also special meanings for ranges for example. range
{rangeX, rangeY, 1} would tell OpenCL that you are addressing a 2d
buffer instead of a 3d buffer. Just by looking at the spec you will
trigger a segfault if you try this with a FloatBuffer.

But i still think we can get the best of both... my current prototype
looks promising so far.

Sidenote:
you can always create a different view for your buffer:
CLBuffer<FloatBuffer> fb = ....;
CLBuffer<ByteBuffer> bb = b.cloneWith(bytebuffer); // view on the same
cl memory region

so.. if you know what you are doing its all fine. I just want to prevent
to introduce something with high bug potential for client code just to
make the api a bit nicer.

Thanks for all the comments!

-michael


--
- - - -
http://michael-bien.com

Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Wibowit
In reply to this post by Michael Bien
What about a situation where buffer contains interleaved data of different types? Using byte offsets would make more sense there.

If your semantic changes aren't consistent and we would have to mix elements with bytes then I'm against that changes. Primitives in Java have always the same size, no matter what the platform or Java version number, so we can even not use constants but literals, ie instead of offset * SizeofFloat, we can use offset * 4.

Did you change the semantic already?
Reply | Threaded
Open this post in threaded view
|

Re: upcoming semantical change for buffer operations

Michael Bien
This post was updated on .
  no it isn't changed yet i am still experimenting with various options.

if you are using some kind of interleaved data you could just use a
CLBuffer<ByteBuffer> and you could address the elements with byte offsets.

semantics of CLBuffer<ByteBuffer> and CLBuffer<?> would not change only
the other types would.

-michael


On 03/14/2011 08:20 PM, Wibowit [via jogamp] wrote:
> What about a situation where buffer contains interleaved data of different
> types? Using byte offsets would make more sense there.
>
> If your semantic changes aren't consistent and we would have to mix elements
> with bytes then I'm against that changes. Primitives in Java have always the
> same size, no matter what the platform or Java version number, so we can
> even not use constants but literals, ie instead of offset * SizeofFloat, we
> can use offset * 4.
>
> Did you change the semantic already?
>
> _______________________________________________
> If you reply to this email, your message will be added to the discussion below:
> http://forum.jogamp.org/upcoming-semantical-change-for-buffer-operations-tp2519021p2677024.html
> To start a new topic under jogamp, email ml-node+762907-380265080-8131@n3.nabble.com
> To unsubscribe from jogamp, visit http://forum.jogamp.org/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=762907&code=YmllbmF0b3JAYXJjb3IuZGV8NzYyOTA3fDQxNTEwMDY0OA==

--
http://michael-bien.com/