Memory Segment efficient array handling
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Apr 1 10:50:17 UTC 2021
Hi,
so, let me start by saying that I agree that,
functionality/usability-wise it would be nice to have something like
this (perhaps in MemoryAccess).
On the efficiency-side of things, I think I'm less sure I actually would
implement anything differently compared to what you have done here. You
are creating segments, then slicing them, then using copyFrom to do a
bulk copy. That's using the API as intended.
I would be surprised if a direct call to Unsafe (which would have to
solve all the addressing issues that MemorySegment.ofArray already does)
would be much faster than that. After all, all this Java code is
optimized by the JIT compiler, which most of the times can see through
stuff like this (e.g. creation of intermediate objects, and such).
As usual, I verify this stuff using JMH - here's a link to a benchmark I
tweaked to add the case you are describing:
https://github.com/mcimadamore/panama-foreign/blob/intArray-bulk-bench/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java#L151
And here's the results:
```
Benchmark Mode Cnt Score Error Units
BulkOps.getIntArraySegments avgt 30 7363.914 ? 154.629 ns/op
BulkOps.getIntArrayUnsafe avgt 30 7316.283 ? 178.241 ns/op
```
As you can see there's little to tell the two apart, so IMHO, diving
into a direct unsafe call to implement this is just not worth it (note
that you'd have to reimplement bound, liveness checks, etc. - which this
benchmark doesn't even do!).
Note also that this benchmark uses a copy size of 100_000 elements,
which you might say is a lot. I also tried with 1_000, and in that case
the segment version seems 2x faster than the unsafe one - go figure. I
would take these numbers with a pinch of salt; the high level bit is
that doing things at the unsafe level is NOT faster.
So, to conclude, usability-wise, these kind of bulk access operations
might be in the spirit of what MemoryAccess already does - e.g. provide
static accessors which implement commonly used feature - but that
doesn't mean that these methods can be written any more efficiently
inside the JDK.
Maurizio
On 01/04/2021 01:41, leerho wrote:
> Folks,
>
> I am in the process of refactoring our code to use FMA (from JDK16) in our
> application. But what I find missing is the ability to do efficient
> getting and putting of arrays with MemorySegments.
>
> What I need to do often is to place part of an existing array into a
> segment at a specific offset and the reverse; getting an array of elements
> from a segment at a specific offset and placing it into an existing array
> at a specific offset. I have looked closely at MemoryAccess and the latest
> ByteBuffer, but I have not found anything quite as flexible as the
> following.
>
> What I have ended up doing is creating an entire class of array methods
> like the following:
>
> public class MemoryArrays {
>> public static void putIntArray(int[] srcArr, long srcIndex, long
>> numInts,
>> MemorySegment dstSeg, long dstOffsetBytes) {
>> MemorySegment srcSeg = MemorySegment.ofArray(srcArr);
>> MemorySegment srcSegSlice = srcSeg.asSlice(srcIndex << 2, numInts <<
>> 2);
>> MemorySegment dstSegSlice = dstSeg.asSlice(dstOffsetBytes, numInts <<
>> 2);
>> dstSegSlice.copyFrom(srcSegSlice);
>> }
>>
>> /* ...Same as above for all primitive types... */
>>
>> public static void getIntArray(MemorySegment srcSeg, long
>> srcOffsetBytes,
>> int[] dstArr, long dstIndex, long numInts) {
>> MemorySegment srcSegSlice = srcSeg.asSlice(srcOffsetBytes, numInts <<
>> 2);
>> MemorySegment dstSeg = MemorySegment.ofArray(dstArr);
>> MemorySegment dstSegSlice = dstSeg.asSlice(dstIndex << 2, numInts <<
>> 2);
>> dstSegSlice.copyFrom(srcSegSlice);
>> }
>>
>> /* ...Same as above for all primitive types... */
>> }
>>
> I would think that if these methods were built-in to FMA either as a
> separate class or included in MemoryAccess, it would be so much more
> efficient. All of these separate
> calls to MemorySegment could be eliminated and the entire method inlined
> with a few lines of C++ code.
>
> If Panama is interested I would be happy to contribute such a class.
>
> Lee.
More information about the panama-dev
mailing list