Closed tpietzsch closed 1 year ago
@mkitti This doesn't work with BufferAccess
yet, but it would be nice to get that to work, and should be feasible. Maybe we could discuss this at some point?
The cade where hasArray
is true should be easy to handle.
https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#hasArray()
https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#array()
For ByteBuffer, you can use the bulk put
and get
methods.
https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(byte[])
This PR adds functionality to extract blocks from
RandomAccessible
into flat primitive arrays. This will be useful for example to copy data toTensor
, to extract blocks for storing into N5, for interfacing CLIJ, for running small algorithm kernels directly on primitive arrays, etc...The only public API introduced is the interface
PrimitiveBlocks<T extends NativeType<T>>
. The static methodPrimitiveBlocks.of(...)
creates aPrimitiveBlocks
accessor for an arbitraryRandomAccessible
source. The methodPrimitiveBlocks.copy(long[] srcPos, Object dest, int[]size)
is then used to copy blocks out of the source into flat primitive arrays. The idea is to provide an interface similar toSystem.arraycopy
.Object dest
is a primitive array of type corresponding toT
.PrimitiveBlocks.of(...)
understands a lot ofView
constructions (that ultimately end in CellImg, ArrayImg, etc) and will try to create an optimized copier. For example, the following will work:The idea of the optimized copier is: Instead of using
RandomAccess
that checks for every pixel whether it enters a newCell
, whether it is out-of-bounds, etc., all these checks are precomputed and then relevant data from eachCell
is copied in one go. The speedup can be dramatic, in particular if the underlying source data is in aCellImg
. Some benchmarks included, here is for example results ofCopyBenchmarkViewPrimitiveBlocks
If a source
RandomAccessible
cannot be understood,PrimitiveBlocks.of(...)
will return a fall-back implementation (based onLoopBuilder
). With the optionalOnFallback
argument ofPrimitiveBlocks.of(...)
it can be configured whether fall-back should beACCEPT
),WARN
) -- the default,IllegalArgumentException
thrown (FAIL
). The warning/exception message explains why the sourceRandomAccessible
requires fall-back.The only really un-supported case is if the pixel type
T
does not map one-to-one to a primitive type. For example,ComplexDoubleType
orUnsigned4BitType
are not supported. (at least not yet).PrimitiveBlocks.copy
is single-threaded, the idea being to parallelize over blocks instead of the copying within a block.PrimitiveBlocks
is not thread-safe in general, but has a methodthreadSafe()
to obtain a thread-safe instance (implemented usingThreadLocal
copies). For example,can safely be used multi-threaded, for example in
CellLoader
s.