Skip to content
1 change: 1 addition & 0 deletions changes/4531.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Expose `blosc.use_threads` via `zarr.config`, allowing users to enable Blosc's internal threading for faster decoding of large single chunks.
17 changes: 17 additions & 0 deletions src/zarr/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"""

from __future__ import annotations
import importlib

from typing import TYPE_CHECKING, Any, Literal, cast

Expand Down Expand Up @@ -57,6 +58,19 @@ class Config(DConfig): # type: ignore[misc]

"""


def set(self, arg=None, **kwargs):
result = super().set(arg, **kwargs)
numcodecs = importlib.import_module("numcodecs")
numcodecs.blosc.use_threads = self.get("blosc.use_threads", False)
return result

def refresh(self, *args, **kwargs):
result = super().refresh(*args, **kwargs)
numcodecs = importlib.import_module("numcodecs")
numcodecs.blosc.use_threads = self.get("blosc.use_threads", False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will behave counter-intuitively if we change the default value in numcodecs to True

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review @d-v-b. You're right about the default behavior. Right now, Zarr hardcodes numcodecs.blosc.use_threads = False. By exposing it in zarr.config with a default of False, we are explicitly preserving Zarr's current behavior.

If numcodecs changes its default in the future, we would just need to update the Zarr config default to match it, or users can override it via zarr.config.set({"blosc.use_threads": True}).

Since you mentioned the comprehensive thread budget design in the issue thread, should I add a note in the docs here warning that this is a temporary escape hatch until the budget system is implemented?

return result

def reset(self) -> None:
self.clear()
self.refresh()
Expand Down Expand Up @@ -107,6 +121,9 @@ def enable_gpu(self) -> ConfigSet:
"async": {"concurrency": 10, "timeout": None},
"threading": {"max_workers": None},
"json_indent": 2,
"blosc": {
"use_threads": False,
},
"codec_pipeline": {
# FusedCodecPipeline is the faster synchronous pipeline, but it stays
# opt-in for now so behavior is unchanged for existing users. Early
Expand Down
8 changes: 8 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,3 +483,11 @@ def test_deprecated_config(key: str) -> None:
with pytest.raises(ValueError):
with zarr.config.set({key: "foo"}):
pass


def test_blosc_use_threads_config() -> None:
import numcodecs

assert numcodecs.blosc.use_threads is False
with config.set({"blosc.use_threads": True}):
assert numcodecs.blosc.use_threads is True
Loading