14
14
import java .util .Map ;
15
15
import java .util .function .Function ;
16
16
import java .util .stream .Collectors ;
17
+ import java .util .stream .Stream ;
17
18
import javax .annotation .Nonnull ;
18
19
import javax .annotation .Nullable ;
19
20
import ucar .ma2 .InvalidRangeException ;
@@ -119,6 +120,7 @@ public static ArrayMetadataBuilder metadataBuilder(ArrayMetadata existingMetadat
119
120
120
121
/**
121
122
* Reads the entire Zarr array into an ucar.ma2.Array.
123
+ * Utilizes no parallelism.
122
124
*
123
125
* @throws ZarrException
124
126
*/
@@ -129,13 +131,38 @@ public ucar.ma2.Array read() throws ZarrException {
129
131
130
132
/**
131
133
* Reads a part of the Zarr array based on a requested offset and shape into an ucar.ma2.Array.
134
+ * Utilizes no parallelism.
132
135
*
133
136
* @param offset
134
137
* @param shape
135
138
* @throws ZarrException
136
139
*/
137
140
@ Nonnull
138
141
public ucar .ma2 .Array read (final long [] offset , final int [] shape ) throws ZarrException {
142
+ return read (offset , shape , false );
143
+ }
144
+
145
+ /**
146
+ * Reads the entire Zarr array into an ucar.ma2.Array.
147
+ *
148
+ * @param parallel
149
+ * @throws ZarrException
150
+ */
151
+ @ Nonnull
152
+ public ucar .ma2 .Array read (final boolean parallel ) throws ZarrException {
153
+ return read (new long [metadata .ndim ()], Utils .toIntArray (metadata .shape ), parallel );
154
+ }
155
+
156
+ /**
157
+ * Reads a part of the Zarr array based on a requested offset and shape into an ucar.ma2.Array.
158
+ *
159
+ * @param offset
160
+ * @param shape
161
+ * @param parallel
162
+ * @throws ZarrException
163
+ */
164
+ @ Nonnull
165
+ public ucar .ma2 .Array read (final long [] offset , final int [] shape , final boolean parallel ) throws ZarrException {
139
166
if (offset .length != metadata .ndim ()) {
140
167
throw new IllegalArgumentException ("'offset' needs to have rank '" + metadata .ndim () + "'." );
141
168
}
@@ -155,43 +182,46 @@ public ucar.ma2.Array read(final long[] offset, final int[] shape) throws ZarrEx
155
182
156
183
final ucar .ma2 .Array outputArray = ucar .ma2 .Array .factory (metadata .dataType .getMA2DataType (),
157
184
shape );
158
- Arrays .stream (IndexingUtils .computeChunkCoords (metadata .shape , chunkShape , offset , shape ))
159
- .forEach (
160
- chunkCoords -> {
161
- try {
162
- final IndexingUtils .ChunkProjection chunkProjection =
163
- IndexingUtils .computeProjection (chunkCoords , metadata .shape , chunkShape , offset ,
164
- shape
165
- );
166
-
167
- if (chunkIsInArray (chunkCoords )) {
168
- MultiArrayUtils .copyRegion (metadata .allocateFillValueChunk (),
169
- chunkProjection .chunkOffset , outputArray , chunkProjection .outOffset ,
170
- chunkProjection .shape
171
- );
172
- }
173
-
174
- final String [] chunkKeys = metadata .chunkKeyEncoding .encodeChunkKey (chunkCoords );
175
- final StoreHandle chunkHandle = storeHandle .resolve (chunkKeys );
176
- if (!chunkHandle .exists ()) {
177
- return ;
178
- }
179
- if (codecPipeline .supportsPartialDecode ()) {
180
- final ucar .ma2 .Array chunkArray = codecPipeline .decodePartial (chunkHandle ,
181
- Utils .toLongArray (chunkProjection .chunkOffset ), chunkProjection .shape );
182
- MultiArrayUtils .copyRegion (chunkArray , new int [metadata .ndim ()], outputArray ,
183
- chunkProjection .outOffset , chunkProjection .shape
184
- );
185
- } else {
186
- MultiArrayUtils .copyRegion (readChunk (chunkCoords ), chunkProjection .chunkOffset ,
187
- outputArray , chunkProjection .outOffset , chunkProjection .shape
188
- );
189
- }
190
-
191
- } catch (ZarrException e ) {
192
- throw new RuntimeException (e );
193
- }
194
- });
185
+ Stream <long []> chunkStream = Arrays .stream (IndexingUtils .computeChunkCoords (metadata .shape , chunkShape , offset , shape ));
186
+ if (parallel ) {
187
+ chunkStream = chunkStream .parallel ();
188
+ }
189
+ chunkStream .forEach (
190
+ chunkCoords -> {
191
+ try {
192
+ final IndexingUtils .ChunkProjection chunkProjection =
193
+ IndexingUtils .computeProjection (chunkCoords , metadata .shape , chunkShape , offset ,
194
+ shape
195
+ );
196
+
197
+ if (chunkIsInArray (chunkCoords )) {
198
+ MultiArrayUtils .copyRegion (metadata .allocateFillValueChunk (),
199
+ chunkProjection .chunkOffset , outputArray , chunkProjection .outOffset ,
200
+ chunkProjection .shape
201
+ );
202
+ }
203
+
204
+ final String [] chunkKeys = metadata .chunkKeyEncoding .encodeChunkKey (chunkCoords );
205
+ final StoreHandle chunkHandle = storeHandle .resolve (chunkKeys );
206
+ if (!chunkHandle .exists ()) {
207
+ return ;
208
+ }
209
+ if (codecPipeline .supportsPartialDecode ()) {
210
+ final ucar .ma2 .Array chunkArray = codecPipeline .decodePartial (chunkHandle ,
211
+ Utils .toLongArray (chunkProjection .chunkOffset ), chunkProjection .shape );
212
+ MultiArrayUtils .copyRegion (chunkArray , new int [metadata .ndim ()], outputArray ,
213
+ chunkProjection .outOffset , chunkProjection .shape
214
+ );
215
+ } else {
216
+ MultiArrayUtils .copyRegion (readChunk (chunkCoords ), chunkProjection .chunkOffset ,
217
+ outputArray , chunkProjection .outOffset , chunkProjection .shape
218
+ );
219
+ }
220
+
221
+ } catch (ZarrException e ) {
222
+ throw new RuntimeException (e );
223
+ }
224
+ });
195
225
return outputArray ;
196
226
}
197
227
@@ -235,6 +265,7 @@ public ucar.ma2.Array readChunk(long[] chunkCoords)
235
265
/**
236
266
* Writes a ucar.ma2.Array into the Zarr array at the beginning of the Zarr array. The shape of
237
267
* the Zarr array needs be large enough for the write.
268
+ * Utilizes no parallelism.
238
269
*
239
270
* @param array
240
271
*/
@@ -245,11 +276,37 @@ public void write(ucar.ma2.Array array) {
245
276
/**
246
277
* Writes a ucar.ma2.Array into the Zarr array at a specified offset. The shape of the Zarr array
247
278
* needs be large enough for the write.
279
+ * Utilizes no parallelism.
248
280
*
249
281
* @param offset
250
282
* @param array
251
283
*/
252
284
public void write (long [] offset , ucar .ma2 .Array array ) {
285
+ write (offset , array , false );
286
+ }
287
+
288
+ /**
289
+ * Writes a ucar.ma2.Array into the Zarr array at the beginning of the Zarr array. The shape of
290
+ * the Zarr array needs be large enough for the write.
291
+ *
292
+ * @param array
293
+ * @param parallel
294
+ */
295
+ public void write (ucar .ma2 .Array array , boolean parallel ) {
296
+ write (new long [metadata .ndim ()], array , parallel );
297
+ }
298
+
299
+
300
+
301
+ /**
302
+ * Writes a ucar.ma2.Array into the Zarr array at a specified offset. The shape of the Zarr array
303
+ * needs be large enough for the write.
304
+ *
305
+ * @param offset
306
+ * @param array
307
+ * @param parallel
308
+ */
309
+ public void write (long [] offset , ucar .ma2 .Array array , boolean parallel ) {
253
310
if (offset .length != metadata .ndim ()) {
254
311
throw new IllegalArgumentException ("'offset' needs to have rank '" + metadata .ndim () + "'." );
255
312
}
@@ -260,34 +317,37 @@ public void write(long[] offset, ucar.ma2.Array array) {
260
317
int [] shape = array .getShape ();
261
318
262
319
final int [] chunkShape = metadata .chunkShape ();
263
- Arrays .stream (IndexingUtils .computeChunkCoords (metadata .shape , chunkShape , offset , shape ))
264
- .forEach (
265
- chunkCoords -> {
266
- try {
267
- final IndexingUtils .ChunkProjection chunkProjection =
268
- IndexingUtils .computeProjection (chunkCoords , metadata .shape , chunkShape , offset ,
269
- shape
270
- );
271
-
272
- ucar .ma2 .Array chunkArray ;
273
- if (IndexingUtils .isFullChunk (chunkProjection .chunkOffset , chunkProjection .shape ,
274
- chunkShape
275
- )) {
276
- chunkArray = array .sectionNoReduce (chunkProjection .outOffset ,
277
- chunkProjection .shape ,
278
- null
279
- );
280
- } else {
281
- chunkArray = readChunk (chunkCoords );
282
- MultiArrayUtils .copyRegion (array , chunkProjection .outOffset , chunkArray ,
283
- chunkProjection .chunkOffset , chunkProjection .shape
284
- );
285
- }
286
- writeChunk (chunkCoords , chunkArray );
287
- } catch (ZarrException | InvalidRangeException e ) {
288
- throw new RuntimeException (e );
289
- }
290
- });
320
+ Stream <long []> chunkStream = Arrays .stream (IndexingUtils .computeChunkCoords (metadata .shape , chunkShape , offset , shape ));
321
+ if (parallel ) {
322
+ chunkStream = chunkStream .parallel ();
323
+ }
324
+ chunkStream .forEach (
325
+ chunkCoords -> {
326
+ try {
327
+ final IndexingUtils .ChunkProjection chunkProjection =
328
+ IndexingUtils .computeProjection (chunkCoords , metadata .shape , chunkShape , offset ,
329
+ shape
330
+ );
331
+
332
+ ucar .ma2 .Array chunkArray ;
333
+ if (IndexingUtils .isFullChunk (chunkProjection .chunkOffset , chunkProjection .shape ,
334
+ chunkShape
335
+ )) {
336
+ chunkArray = array .sectionNoReduce (chunkProjection .outOffset ,
337
+ chunkProjection .shape ,
338
+ null
339
+ );
340
+ } else {
341
+ chunkArray = readChunk (chunkCoords );
342
+ MultiArrayUtils .copyRegion (array , chunkProjection .outOffset , chunkArray ,
343
+ chunkProjection .chunkOffset , chunkProjection .shape
344
+ );
345
+ }
346
+ writeChunk (chunkCoords , chunkArray );
347
+ } catch (ZarrException | InvalidRangeException e ) {
348
+ throw new RuntimeException (e );
349
+ }
350
+ });
291
351
}
292
352
293
353
/**
@@ -434,6 +494,5 @@ public void write(@Nonnull ucar.ma2.Array content) throws ZarrException {
434
494
}
435
495
array .write (offset , content );
436
496
}
437
-
438
497
}
439
498
}
0 commit comments