@@ -17,6 +17,7 @@ import shutil
17
17
import tempfile
18
18
from collections import namedtuple
19
19
from glob import glob
20
+ import multiprocessing
20
21
import fasteners
21
22
22
23
@@ -52,6 +53,14 @@ cdef extern from "blosc.h":
52
53
BLOSC_VERSION_STRING,
53
54
BLOSC_VERSION_DATE
54
55
56
+ void blosc_init()
57
+ void blosc_destroy()
58
+ int blosc_set_nthreads(int nthreads)
59
+ int blosc_set_compressor(const char * compname)
60
+ int blosc_compress(int clevel, int doshuffle, size_t typesize,
61
+ size_t nbytes, void * src, void * dest,
62
+ size_t destsize) nogil
63
+ int blosc_decompress(void * src, void * dest, size_t destsize) nogil
55
64
int blosc_compname_to_compcode(const char * compname)
56
65
int blosc_compress_ctx(int clevel, int doshuffle, size_t typesize,
57
66
size_t nbytes, const void * src, void * dest,
@@ -64,7 +73,7 @@ cdef extern from "blosc.h":
64
73
65
74
66
75
def blosc_version ():
67
- """ Return the version of c- blosc that zarr was compiled with."""
76
+ """ Return the version of blosc that zarr was compiled with."""
68
77
69
78
# all the 'decode' contorsions are for Python 3 returning actual strings
70
79
ver_str = < char * > BLOSC_VERSION_STRING
@@ -76,6 +85,43 @@ def blosc_version():
76
85
return ver_str, ver_date
77
86
78
87
88
+ def init ():
89
+ blosc_init()
90
+
91
+
92
+ def destroy ():
93
+ blosc_destroy()
94
+
95
+
96
+ _blosc_use_context = False
97
+
98
+
99
+ def set_blosc_options (use_context = False , nthreads = None ):
100
+ """ Set options for how the blosc compressor is used.
101
+
102
+ Parameters
103
+ ----------
104
+ use_context : bool, optional
105
+ If False, blosc will be used in non-contextual mode, which is best
106
+ when using zarr in a single-threaded environment because it allows
107
+ blosc to use multiple threads internally. If True, blosc will be used
108
+ in contextual mode, which is better when using zarr in a
109
+ multi-threaded environment like dask.array because it avoids the blosc
110
+ global lock and so multiple blosc operations can be running
111
+ concurrently.
112
+ nthreads : int, optional
113
+ Number of internal threads to use when running blosc in non-contextual
114
+ mode.
115
+
116
+ """
117
+ global _blosc_use_context
118
+ _blosc_use_context = use_context
119
+ if not use_context:
120
+ if nthreads is None :
121
+ nthreads = multiprocessing.cpu_count()
122
+ blosc_set_nthreads(nthreads)
123
+
124
+
79
125
# ##############################################################################
80
126
# DEBUG LOGGING #
81
127
# ##############################################################################
@@ -122,7 +168,7 @@ def _normalize_cparams(cname=None, clevel=None, shuffle=None):
122
168
cname = cname.encode()
123
169
# check compressor is available
124
170
if blosc_compname_to_compcode(cname) < 0 :
125
- raise ValueError (" compressor not available: %s " % cname)
171
+ raise ValueError (' compressor not available: %s ' % cname)
126
172
127
173
# determine compression level
128
174
clevel = clevel if clevel is not None else defaults.clevel
@@ -389,8 +435,12 @@ cdef class Chunk(BaseChunk):
389
435
cdef int ret
390
436
391
437
# do decompression
392
- with nogil:
393
- ret = blosc_decompress_ctx(self ._data, dest, self ._nbytes, 1 )
438
+ if _blosc_use_context:
439
+ with nogil:
440
+ ret = blosc_decompress_ctx(self ._data, dest, self ._nbytes, 1 )
441
+ else :
442
+ with nogil:
443
+ ret = blosc_decompress(self ._data, dest, self ._nbytes)
394
444
395
445
# handle errors
396
446
if ret <= 0 :
@@ -408,12 +458,20 @@ cdef class Chunk(BaseChunk):
408
458
dest = < char * > malloc(self ._nbytes + BLOSC_MAX_OVERHEAD)
409
459
410
460
# perform compression
411
- with nogil:
412
- cbytes = blosc_compress_ctx(self ._clevel, self ._shuffle,
413
- self ._itemsize, self ._nbytes,
414
- source, dest,
415
- self ._nbytes + BLOSC_MAX_OVERHEAD,
416
- self ._cname, 0 , 1 )
461
+ if _blosc_use_context:
462
+ with nogil:
463
+ cbytes = blosc_compress_ctx(self ._clevel, self ._shuffle,
464
+ self ._itemsize, self ._nbytes,
465
+ source, dest,
466
+ self ._nbytes + BLOSC_MAX_OVERHEAD,
467
+ self ._cname, 0 , 1 )
468
+ else :
469
+ # compressor should have been checked already
470
+ assert blosc_set_compressor(self ._cname) >= 0
471
+ with nogil:
472
+ cbytes = blosc_compress(self ._clevel, self ._shuffle,
473
+ self ._itemsize, self ._nbytes, source,
474
+ dest, self ._nbytes + BLOSC_MAX_OVERHEAD)
417
475
418
476
# check compression was successful
419
477
if cbytes <= 0 :
@@ -505,8 +563,12 @@ cdef class PersistentChunk(BaseChunk):
505
563
source = PyBytes_AsString(data)
506
564
507
565
# do decompression
508
- with nogil:
509
- ret = blosc_decompress_ctx(source, dest, self ._nbytes, 1 )
566
+ if _blosc_use_context:
567
+ with nogil:
568
+ ret = blosc_decompress_ctx(source, dest, self ._nbytes, 1 )
569
+ else :
570
+ with nogil:
571
+ ret = blosc_decompress(source, dest, self ._nbytes)
510
572
511
573
# handle errors
512
574
if ret <= 0 :
@@ -542,12 +604,20 @@ cdef class PersistentChunk(BaseChunk):
542
604
dest = < char * > malloc(self ._nbytes + BLOSC_MAX_OVERHEAD)
543
605
544
606
# perform compression
545
- with nogil:
546
- cbytes = blosc_compress_ctx(self ._clevel, self ._shuffle,
547
- self ._itemsize, self ._nbytes,
548
- source, dest,
549
- self ._nbytes + BLOSC_MAX_OVERHEAD,
550
- self ._cname, 0 , 1 )
607
+ if _blosc_use_context:
608
+ with nogil:
609
+ cbytes = blosc_compress_ctx(self ._clevel, self ._shuffle,
610
+ self ._itemsize, self ._nbytes,
611
+ source, dest,
612
+ self ._nbytes + BLOSC_MAX_OVERHEAD,
613
+ self ._cname, 0 , 1 )
614
+ else :
615
+ # compressor should have been checked already
616
+ assert blosc_set_compressor(self ._cname) >= 0
617
+ with nogil:
618
+ cbytes = blosc_compress(self ._clevel, self ._shuffle,
619
+ self ._itemsize, self ._nbytes, source,
620
+ dest, self ._nbytes + BLOSC_MAX_OVERHEAD)
551
621
552
622
# check compression was successful
553
623
if cbytes <= 0 :
@@ -1321,6 +1391,7 @@ cdef class SynchronizedPersistentArray(PersistentArray):
1321
1391
# ##############################################################################
1322
1392
1323
1393
1394
+ # noinspection PyUnresolvedReferences,PyProtectedMember
1324
1395
cdef _lazy_get_chunk(BaseArray array, tuple cidx):
1325
1396
try :
1326
1397
chunk = array._cdata[cidx]
0 commit comments