comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/threadpoolctl-3.5.0.dist-info/METADATA @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 69:33d812a61356
1 Metadata-Version: 2.1
2 Name: threadpoolctl
3 Version: 3.5.0
4 Summary: threadpoolctl
5 Home-page: https://github.com/joblib/threadpoolctl
6 License: BSD-3-Clause
7 Author: Thomas Moreau
8 Author-email: thomas.moreau.2010@gmail.com
9 Requires-Python: >=3.8
10 Description-Content-Type: text/markdown
11 Classifier: Intended Audience :: Developers
12 Classifier: License :: OSI Approved :: BSD License
13 Classifier: Programming Language :: Python :: 3
14 Classifier: Programming Language :: Python :: 3.8
15 Classifier: Programming Language :: Python :: 3.9
16 Classifier: Programming Language :: Python :: 3.10
17 Classifier: Programming Language :: Python :: 3.11
18 Classifier: Programming Language :: Python :: 3.12
19 Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
21 # Thread-pool Controls [![Build Status](https://dev.azure.com/joblib/threadpoolctl/_apis/build/status/joblib.threadpoolctl?branchName=master)](https://dev.azure.com/joblib/threadpoolctl/_build/latest?definitionId=1&branchName=master) [![codecov](https://codecov.io/gh/joblib/threadpoolctl/branch/master/graph/badge.svg)](https://codecov.io/gh/joblib/threadpoolctl)
22
23 Python helpers to limit the number of threads used in the
24 threadpool-backed of common native libraries used for scientific
25 computing and data science (e.g. BLAS and OpenMP).
26
27 Fine control of the underlying thread-pool size can be useful in
28 workloads that involve nested parallelism so as to mitigate
29 oversubscription issues.
30
31 ## Installation
32
33 - For users, install the last published version from PyPI:
34
35 ```bash
36 pip install threadpoolctl
37 ```
38
39 - For contributors, install from the source repository in developer
40 mode:
41
42 ```bash
43 pip install -r dev-requirements.txt
44 flit install --symlink
45 ```
46
47 then you run the tests with pytest:
48
49 ```bash
50 pytest
51 ```
52
53 ## Usage
54
55 ### Command Line Interface
56
57 Get a JSON description of thread-pools initialized when importing python
58 packages such as numpy or scipy for instance:
59
60 ```
61 python -m threadpoolctl -i numpy scipy.linalg
62 [
63 {
64 "filepath": "/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so",
65 "prefix": "libmkl_rt",
66 "user_api": "blas",
67 "internal_api": "mkl",
68 "version": "2019.0.4",
69 "num_threads": 2,
70 "threading_layer": "intel"
71 },
72 {
73 "filepath": "/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so",
74 "prefix": "libiomp",
75 "user_api": "openmp",
76 "internal_api": "openmp",
77 "version": null,
78 "num_threads": 4
79 }
80 ]
81 ```
82
83 The JSON information is written on STDOUT. If some of the packages are missing,
84 a warning message is displayed on STDERR.
85
86 ### Python Runtime Programmatic Introspection
87
88 Introspect the current state of the threadpool-enabled runtime libraries
89 that are loaded when importing Python packages:
90
91 ```python
92 >>> from threadpoolctl import threadpool_info
93 >>> from pprint import pprint
94 >>> pprint(threadpool_info())
95 []
96
97 >>> import numpy
98 >>> pprint(threadpool_info())
99 [{'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so',
100 'internal_api': 'mkl',
101 'num_threads': 2,
102 'prefix': 'libmkl_rt',
103 'threading_layer': 'intel',
104 'user_api': 'blas',
105 'version': '2019.0.4'},
106 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so',
107 'internal_api': 'openmp',
108 'num_threads': 4,
109 'prefix': 'libiomp',
110 'user_api': 'openmp',
111 'version': None}]
112
113 >>> import xgboost
114 >>> pprint(threadpool_info())
115 [{'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so',
116 'internal_api': 'mkl',
117 'num_threads': 2,
118 'prefix': 'libmkl_rt',
119 'threading_layer': 'intel',
120 'user_api': 'blas',
121 'version': '2019.0.4'},
122 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so',
123 'internal_api': 'openmp',
124 'num_threads': 4,
125 'prefix': 'libiomp',
126 'user_api': 'openmp',
127 'version': None},
128 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libgomp.so.1.0.0',
129 'internal_api': 'openmp',
130 'num_threads': 4,
131 'prefix': 'libgomp',
132 'user_api': 'openmp',
133 'version': None}]
134 ```
135
136 In the above example, `numpy` was installed from the default anaconda channel and comes
137 with MKL and its Intel OpenMP (`libiomp5`) implementation while `xgboost` was installed
138 from pypi.org and links against GNU OpenMP (`libgomp`) so both OpenMP runtimes are
139 loaded in the same Python program.
140
141 The state of these libraries is also accessible through the object oriented API:
142
143 ```python
144 >>> from threadpoolctl import ThreadpoolController, threadpool_info
145 >>> from pprint import pprint
146 >>> import numpy
147 >>> controller = ThreadpoolController()
148 >>> pprint(controller.info())
149 [{'architecture': 'Haswell',
150 'filepath': '/home/jeremie/miniconda/envs/dev/lib/libopenblasp-r0.3.17.so',
151 'internal_api': 'openblas',
152 'num_threads': 4,
153 'prefix': 'libopenblas',
154 'threading_layer': 'pthreads',
155 'user_api': 'blas',
156 'version': '0.3.17'}]
157
158 >>> controller.info() == threadpool_info()
159 True
160 ```
161
162 ### Setting the Maximum Size of Thread-Pools
163
164 Control the number of threads used by the underlying runtime libraries
165 in specific sections of your Python program:
166
167 ```python
168 >>> from threadpoolctl import threadpool_limits
169 >>> import numpy as np
170
171 >>> with threadpool_limits(limits=1, user_api='blas'):
172 ... # In this block, calls to blas implementation (like openblas or MKL)
173 ... # will be limited to use only one thread. They can thus be used jointly
174 ... # with thread-parallelism.
175 ... a = np.random.randn(1000, 1000)
176 ... a_squared = a @ a
177 ```
178
179 The threadpools can also be controlled via the object oriented API, which is especially
180 useful to avoid searching through all the loaded shared libraries each time. It will
181 however not act on libraries loaded after the instantiation of the
182 `ThreadpoolController`:
183
184 ```python
185 >>> from threadpoolctl import ThreadpoolController
186 >>> import numpy as np
187 >>> controller = ThreadpoolController()
188
189 >>> with controller.limit(limits=1, user_api='blas'):
190 ... a = np.random.randn(1000, 1000)
191 ... a_squared = a @ a
192 ```
193
194 ### Restricting the limits to the scope of a function
195
196 `threadpool_limits` and `ThreadpoolController` can also be used as decorators to set
197 the maximum number of threads used by the supported libraries at a function level. The
198 decorators are accessible through their `wrap` method:
199
200 ```python
201 >>> from threadpoolctl import ThreadpoolController, threadpool_limits
202 >>> import numpy as np
203 >>> controller = ThreadpoolController()
204
205 >>> @controller.wrap(limits=1, user_api='blas')
206 ... # or @threadpool_limits.wrap(limits=1, user_api='blas')
207 ... def my_func():
208 ... # Inside this function, calls to blas implementation (like openblas or MKL)
209 ... # will be limited to use only one thread.
210 ... a = np.random.randn(1000, 1000)
211 ... a_squared = a @ a
212 ...
213 ```
214
215 ### Switching the FlexiBLAS backend
216
217 `FlexiBLAS` is a BLAS wrapper for which the BLAS backend can be switched at runtime.
218 `threadpoolctl` exposes python bindings for this feature. Here's an example but note
219 that this part of the API is experimental and subject to change without deprecation:
220
221 ```python
222 >>> from threadpoolctl import ThreadpoolController
223 >>> import numpy as np
224 >>> controller = ThreadpoolController()
225
226 >>> controller.info()
227 [{'user_api': 'blas',
228 'internal_api': 'flexiblas',
229 'num_threads': 1,
230 'prefix': 'libflexiblas',
231 'filepath': '/usr/local/lib/libflexiblas.so.3.3',
232 'version': '3.3.1',
233 'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],
234 'loaded_backends': ['NETLIB'],
235 'current_backend': 'NETLIB'}]
236
237 # Retrieve the flexiblas controller
238 >>> flexiblas_ct = controller.select(internal_api="flexiblas").lib_controllers[0]
239
240 # Switch the backend with one predefined at build time (listed in "available_backends")
241 >>> flexiblas_ct.switch_backend("OPENBLASPTHREAD")
242 >>> controller.info()
243 [{'user_api': 'blas',
244 'internal_api': 'flexiblas',
245 'num_threads': 4,
246 'prefix': 'libflexiblas',
247 'filepath': '/usr/local/lib/libflexiblas.so.3.3',
248 'version': '3.3.1',
249 'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],
250 'loaded_backends': ['NETLIB', 'OPENBLASPTHREAD'],
251 'current_backend': 'OPENBLASPTHREAD'},
252 {'user_api': 'blas',
253 'internal_api': 'openblas',
254 'num_threads': 4,
255 'prefix': 'libopenblas',
256 'filepath': '/usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so',
257 'version': '0.3.8',
258 'threading_layer': 'pthreads',
259 'architecture': 'Haswell'}]
260
261 # It's also possible to directly give the path to a shared library
262 >>> flexiblas_controller.switch_backend("/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so")
263 >>> controller.info()
264 [{'user_api': 'blas',
265 'internal_api': 'flexiblas',
266 'num_threads': 2,
267 'prefix': 'libflexiblas',
268 'filepath': '/usr/local/lib/libflexiblas.so.3.3',
269 'version': '3.3.1',
270 'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],
271 'loaded_backends': ['NETLIB',
272 'OPENBLASPTHREAD',
273 '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so'],
274 'current_backend': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so'},
275 {'user_api': 'openmp',
276 'internal_api': 'openmp',
277 'num_threads': 4,
278 'prefix': 'libomp',
279 'filepath': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libomp.so',
280 'version': None},
281 {'user_api': 'blas',
282 'internal_api': 'openblas',
283 'num_threads': 4,
284 'prefix': 'libopenblas',
285 'filepath': '/usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so',
286 'version': '0.3.8',
287 'threading_layer': 'pthreads',
288 'architecture': 'Haswell'},
289 {'user_api': 'blas',
290 'internal_api': 'mkl',
291 'num_threads': 2,
292 'prefix': 'libmkl_rt',
293 'filepath': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so.2',
294 'version': '2024.0-Product',
295 'threading_layer': 'gnu'}]
296 ```
297
298 You can observe that the previously linked OpenBLAS shared object stays loaded by
299 the Python program indefinitely, but FlexiBLAS itself no longer delegates BLAS calls
300 to OpenBLAS as indicated by the `current_backend` attribute.
301 ### Writing a custom library controller
302
303 Currently, `threadpoolctl` has support for `OpenMP` and the main `BLAS` libraries.
304 However it can also be used to control the threadpool of other native libraries,
305 provided that they expose an API to get and set the limit on the number of threads.
306 For that, one must implement a controller for this library and register it to
307 `threadpoolctl`.
308
309 A custom controller must be a subclass of the `LibController` class and implement
310 the attributes and methods described in the docstring of `LibController`. Then this
311 new controller class must be registered using the `threadpoolctl.register` function.
312 An complete example can be found [here](
313 https://github.com/joblib/threadpoolctl/blob/master/tests/_pyMylib/__init__.py).
314
315 ### Sequential BLAS within OpenMP parallel region
316
317 When one wants to have sequential BLAS calls within an OpenMP parallel region, it's
318 safer to set `limits="sequential_blas_under_openmp"` since setting `limits=1` and
319 `user_api="blas"` might not lead to the expected behavior in some configurations
320 (e.g. OpenBLAS with the OpenMP threading layer
321 https://github.com/xianyi/OpenBLAS/issues/2985).
322
323 ### Known Limitations
324
325 - `threadpool_limits` can fail to limit the number of inner threads when nesting
326 parallel loops managed by distinct OpenMP runtime implementations (for instance
327 libgomp from GCC and libomp from clang/llvm or libiomp from ICC).
328
329 See the `test_openmp_nesting` function in [tests/test_threadpoolctl.py](
330 https://github.com/joblib/threadpoolctl/blob/master/tests/test_threadpoolctl.py)
331 for an example. More information can be found at:
332 https://github.com/jeremiedbb/Nested_OpenMP
333
334 Note however that this problem does not happen when `threadpool_limits` is
335 used to limit the number of threads used internally by BLAS calls that are
336 themselves nested under OpenMP parallel loops. `threadpool_limits` works as
337 expected, even if the inner BLAS implementation relies on a distinct OpenMP
338 implementation.
339
340 - Using Intel OpenMP (ICC) and LLVM OpenMP (clang) in the same Python program
341 under Linux is known to cause problems. See the following guide for more details
342 and workarounds:
343 https://github.com/joblib/threadpoolctl/blob/master/multiple_openmp.md
344
345 - Setting the maximum number of threads of the OpenMP and BLAS libraries has a global
346 effect and impacts the whole Python process. There is no thread level isolation as
347 these libraries do not offer thread-local APIs to configure the number of threads to
348 use in nested parallel calls.
349
350
351 ## Maintainers
352
353 To make a release:
354
355 - Bump the version number (`__version__`) in `threadpoolctl.py` and update the
356 release date in `CHANGES.md`.
357
358 - Build the distribution archives:
359
360 ```bash
361 pip install flit
362 flit build
363 ```
364
365 and check the contents of `dist/`.
366
367 - If everything is fine, make a commit for the release, tag it and push the
368 tag to github:
369
370 ```bash
371 git tag -a X.Y.Z
372 git push git@github.com:joblib/threadpoolctl.git X.Y.Z
373 ```
374
375 - Upload the wheels and source distribution to PyPI using flit. Since PyPI doesn't
376 allow password authentication anymore, the username needs to be changed to the
377 generic name `__token__`:
378
379 ```bash
380 FLIT_USERNAME=__token__ flit publish
381 ```
382
383 and a PyPI token has to be passed in place of the password.
384
385 - Create a PR for the release on the [conda-forge feedstock](https://github.com/conda-forge/threadpoolctl-feedstock) (or wait for the bot to make it).
386
387 - Publish the release on github.
388
389 ### Credits
390
391 The initial dynamic library introspection code was written by @anton-malakhov
392 for the smp package available at https://github.com/IntelPython/smp .
393
394 threadpoolctl extends this for other operating systems. Contrary to smp,
395 threadpoolctl does not attempt to limit the size of Python multiprocessing
396 pools (threads or processes) or set operating system-level CPU affinity
397 constraints: threadpoolctl only interacts with native libraries via their
398 public runtime APIs.
399