Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
in package metadata.
https://github.com/joblib/threadpoolctl/issues/251

- When passing a list of dicts or a dict to `threadpool_limits(limit=...)` and
related APIs, the `"filepath"` is used as the unique key identifying
``LibController``s, if available, falling back to ``"prefix"``. Previously the
``"prefix"`` was checked first.
https://github.com/joblib/threadpoolctl/issues/257

3.7.0 (2026-09-15)
==================

Expand Down
35 changes: 18 additions & 17 deletions threadpoolctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ class _ThreadpoolLimiter:

def __init__(self, controller, *, limits=None, user_api=None):
self._controller = controller
self._limits, self._user_api, self._prefixes = self._check_params(
self._limits, self._user_api = self._check_params(
limits, user_api
)
self._original_info = self._controller.info()
Expand Down Expand Up @@ -820,7 +820,7 @@ def get_original_num_threads(self):
return num_threads

def _check_params(self, limits, user_api):
"""Suitable values for the _limits, _user_api and _prefixes attributes"""
"""Suitable values for the _limits and _user_api attributes"""

if isinstance(limits, str) and limits == "sequential_blas_under_openmp":
(
Expand All @@ -841,19 +841,23 @@ def _check_params(self, limits, user_api):

if limits is not None:
limits = {api: limits for api in user_api}
prefixes = []
else:
if isinstance(limits, list):
# This should be a list of dicts of library info, for
# compatibility with the result from threadpool_info.
limits = {
lib_info["prefix"]: lib_info["num_threads"] for lib_info in limits
# Use prefix key for backwards compatibility with older
# versions that didn't use the filepath as the key.
lib_info.get("filepath", lib_info["prefix"]): lib_info[
"num_threads"
]
for lib_info in limits
}
elif isinstance(limits, ThreadpoolController):
# To set the limits from the library controllers of a
# ThreadpoolController object.
limits = {
lib_controller.prefix: lib_controller.num_threads
lib_controller.filepath: lib_controller.num_threads
for lib_controller in limits.lib_controllers
}

Expand All @@ -865,25 +869,22 @@ def _check_params(self, limits, user_api):

# With a dictionary, can set both specific limit for given
# libraries and global limit for user_api. Fetch each separately.
prefixes = [prefix for prefix in limits if prefix in _ALL_PREFIXES]
user_api = [api for api in limits if api in _ALL_USER_APIS]

return limits, user_api, prefixes
return limits, user_api

def _set_threadpool_limits(self):
"""Change the maximal number of threads in selected thread pools.

Return a list with all the supported libraries that have been found
matching `self._prefixes` and `self._user_api`.
"""
"""Change the maximal number of threads in selected thread pools."""
if self._limits is None:
return

for lib_controller in self._controller.lib_controllers:
# self._limits is a dict {key: num_threads} where key is either
# a prefix or a user_api. If a library matches both, the limit
# corresponding to the prefix is chosen.
if lib_controller.prefix in self._limits:
# self._limits is a dict {key: num_threads} where key is either a
# filepath, a prefix, or a user_api. Libraries are matched in that
# order.
if lib_controller.filepath in self._limits:
num_threads = self._limits[lib_controller.filepath]
elif lib_controller.prefix in self._limits:
num_threads = self._limits[lib_controller.prefix]
elif lib_controller.user_api in self._limits:
num_threads = self._limits[lib_controller.user_api]
Expand All @@ -898,7 +899,7 @@ class _ThreadpoolLimiterDecorator(_ThreadpoolLimiter, ContextDecorator):
"""Same as _ThreadpoolLimiter but to be used as a decorator"""

def __init__(self, controller, *, limits=None, user_api=None):
self._limits, self._user_api, self._prefixes = self._check_params(
self._limits, self._user_api = self._check_params(
limits, user_api
)
self._controller = controller
Expand Down
Loading