CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
1Metadata-Version: 2.42Name: threadpoolctl3Version: 3.6.04Summary: threadpoolctl5Home-page: https://github.com/joblib/threadpoolctl6Author: Thomas Moreau7Author-email: thomas.moreau.2010@gmail.com8Requires-Python: >=3.99Description-Content-Type: text/markdown10License: BSD-3-Clause11Classifier: Intended Audience :: Developers12Classifier: License :: OSI Approved :: BSD License13Classifier: Programming Language :: Python :: 314Classifier: Programming Language :: Python :: 3.915Classifier: Programming Language :: Python :: 3.1016Classifier: Programming Language :: Python :: 3.1117Classifier: Programming Language :: Python :: 3.1218Classifier: Programming Language :: Python :: 3.1319Classifier: Topic :: Software Development :: Libraries :: Python Modules20License-File: LICENSE21 22# Thread-pool Controls [![Build Status](https://github.com/joblib/threadpoolctl/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/joblib/threadpoolctl/actions?query=branch%3Amaster) [![codecov](https://codecov.io/gh/joblib/threadpoolctl/branch/master/graph/badge.svg)](https://codecov.io/gh/joblib/threadpoolctl)23 24Python helpers to limit the number of threads used in the25threadpool-backed of common native libraries used for scientific26computing and data science (e.g. BLAS and OpenMP).27 28Fine control of the underlying thread-pool size can be useful in29workloads that involve nested parallelism so as to mitigate30oversubscription issues.31 32## Installation33 34- For users, install the last published version from PyPI:35 36  ```bash37  pip install threadpoolctl38  ```39 40- For contributors, install from the source repository in developer41  mode:42 43  ```bash44  pip install -r dev-requirements.txt45  flit install --symlink46  ```47 48  then you run the tests with pytest:49 50  ```bash51  pytest52  ```53 54## Usage55 56### Command Line Interface57 58Get a JSON description of thread-pools initialized when importing python59packages such as numpy or scipy for instance:60 61```62python -m threadpoolctl -i numpy scipy.linalg63[64  {65    "filepath": "/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so",66    "prefix": "libmkl_rt",67    "user_api": "blas",68    "internal_api": "mkl",69    "version": "2019.0.4",70    "num_threads": 2,71    "threading_layer": "intel"72  },73  {74    "filepath": "/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so",75    "prefix": "libiomp",76    "user_api": "openmp",77    "internal_api": "openmp",78    "version": null,79    "num_threads": 480  }81]82```83 84The JSON information is written on STDOUT. If some of the packages are missing,85a warning message is displayed on STDERR.86 87### Python Runtime Programmatic Introspection88 89Introspect the current state of the threadpool-enabled runtime libraries90that are loaded when importing Python packages:91 92```python93>>> from threadpoolctl import threadpool_info94>>> from pprint import pprint95>>> pprint(threadpool_info())96[]97 98>>> import numpy99>>> pprint(threadpool_info())100[{'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so',101  'internal_api': 'mkl',102  'num_threads': 2,103  'prefix': 'libmkl_rt',104  'threading_layer': 'intel',105  'user_api': 'blas',106  'version': '2019.0.4'},107 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so',108  'internal_api': 'openmp',109  'num_threads': 4,110  'prefix': 'libiomp',111  'user_api': 'openmp',112  'version': None}]113 114>>> import xgboost115>>> pprint(threadpool_info())116[{'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libmkl_rt.so',117  'internal_api': 'mkl',118  'num_threads': 2,119  'prefix': 'libmkl_rt',120  'threading_layer': 'intel',121  'user_api': 'blas',122  'version': '2019.0.4'},123 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libiomp5.so',124  'internal_api': 'openmp',125  'num_threads': 4,126  'prefix': 'libiomp',127  'user_api': 'openmp',128  'version': None},129 {'filepath': '/home/ogrisel/miniconda3/envs/tmp/lib/libgomp.so.1.0.0',130  'internal_api': 'openmp',131  'num_threads': 4,132  'prefix': 'libgomp',133  'user_api': 'openmp',134  'version': None}]135```136 137In the above example, `numpy` was installed from the default anaconda channel and comes138with MKL and its Intel OpenMP (`libiomp5`) implementation while `xgboost` was installed139from pypi.org and links against GNU OpenMP (`libgomp`) so both OpenMP runtimes are140loaded in the same Python program.141 142The state of these libraries is also accessible through the object oriented API:143 144```python145>>> from threadpoolctl import ThreadpoolController, threadpool_info146>>> from pprint import pprint147>>> import numpy148>>> controller = ThreadpoolController()149>>> pprint(controller.info())150[{'architecture': 'Haswell',151  'filepath': '/home/jeremie/miniconda/envs/dev/lib/libopenblasp-r0.3.17.so',152  'internal_api': 'openblas',153  'num_threads': 4,154  'prefix': 'libopenblas',155  'threading_layer': 'pthreads',156  'user_api': 'blas',157  'version': '0.3.17'}]158 159>>> controller.info() == threadpool_info()160True161```162 163### Setting the Maximum Size of Thread-Pools164 165Control the number of threads used by the underlying runtime libraries166in specific sections of your Python program:167 168```python169>>> from threadpoolctl import threadpool_limits170>>> import numpy as np171 172>>> with threadpool_limits(limits=1, user_api='blas'):173...     # In this block, calls to blas implementation (like openblas or MKL)174...     # will be limited to use only one thread. They can thus be used jointly175...     # with thread-parallelism.176...     a = np.random.randn(1000, 1000)177...     a_squared = a @ a178```179 180The threadpools can also be controlled via the object oriented API, which is especially181useful to avoid searching through all the loaded shared libraries each time. It will182however not act on libraries loaded after the instantiation of the183`ThreadpoolController`:184 185```python186>>> from threadpoolctl import ThreadpoolController187>>> import numpy as np188>>> controller = ThreadpoolController()189 190>>> with controller.limit(limits=1, user_api='blas'):191...     a = np.random.randn(1000, 1000)192...     a_squared = a @ a193```194 195### Restricting the limits to the scope of a function196 197`threadpool_limits` and `ThreadpoolController` can also be used as decorators to set198the maximum number of threads used by the supported libraries at a function level. The199decorators are accessible through their `wrap` method:200 201```python202>>> from threadpoolctl import ThreadpoolController, threadpool_limits203>>> import numpy as np204>>> controller = ThreadpoolController()205 206>>> @controller.wrap(limits=1, user_api='blas')207... # or @threadpool_limits.wrap(limits=1, user_api='blas')208... def my_func():209...     # Inside this function, calls to blas implementation (like openblas or MKL)210...     # will be limited to use only one thread.211...     a = np.random.randn(1000, 1000)212...     a_squared = a @ a213...214```215 216### Switching the FlexiBLAS backend217 218`FlexiBLAS` is a BLAS wrapper for which the BLAS backend can be switched at runtime.219`threadpoolctl` exposes python bindings for this feature. Here's an example but note220that this part of the API is experimental and subject to change without deprecation:221 222```python223>>> from threadpoolctl import ThreadpoolController224>>> import numpy as np225>>> controller = ThreadpoolController()226 227>>> controller.info()228[{'user_api': 'blas',229  'internal_api': 'flexiblas',230  'num_threads': 1,231  'prefix': 'libflexiblas',232  'filepath': '/usr/local/lib/libflexiblas.so.3.3',233  'version': '3.3.1',234  'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],235  'loaded_backends': ['NETLIB'],236  'current_backend': 'NETLIB'}]237 238# Retrieve the flexiblas controller239>>> flexiblas_ct = controller.select(internal_api="flexiblas").lib_controllers[0]240 241# Switch the backend with one predefined at build time (listed in "available_backends")242>>> flexiblas_ct.switch_backend("OPENBLASPTHREAD")243>>> controller.info()244[{'user_api': 'blas',245  'internal_api': 'flexiblas',246  'num_threads': 4,247  'prefix': 'libflexiblas',248  'filepath': '/usr/local/lib/libflexiblas.so.3.3',249  'version': '3.3.1',250  'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],251  'loaded_backends': ['NETLIB', 'OPENBLASPTHREAD'],252  'current_backend': 'OPENBLASPTHREAD'},253 {'user_api': 'blas',254  'internal_api': 'openblas',255  'num_threads': 4,256  'prefix': 'libopenblas',257  'filepath': '/usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so',258  'version': '0.3.8',259  'threading_layer': 'pthreads',260  'architecture': 'Haswell'}]261 262# It's also possible to directly give the path to a shared library263>>> flexiblas_controller.switch_backend("/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so")264>>> controller.info()265[{'user_api': 'blas',266  'internal_api': 'flexiblas',267  'num_threads': 2,268  'prefix': 'libflexiblas',269  'filepath': '/usr/local/lib/libflexiblas.so.3.3',270  'version': '3.3.1',271  'available_backends': ['NETLIB', 'OPENBLASPTHREAD', 'ATLAS'],272  'loaded_backends': ['NETLIB',273   'OPENBLASPTHREAD',274   '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so'],275  'current_backend': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so'},276 {'user_api': 'openmp',277  'internal_api': 'openmp',278  'num_threads': 4,279  'prefix': 'libomp',280  'filepath': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libomp.so',281  'version': None},282 {'user_api': 'blas',283  'internal_api': 'openblas',284  'num_threads': 4,285  'prefix': 'libopenblas',286  'filepath': '/usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so',287  'version': '0.3.8',288  'threading_layer': 'pthreads',289  'architecture': 'Haswell'},290 {'user_api': 'blas',291  'internal_api': 'mkl',292  'num_threads': 2,293  'prefix': 'libmkl_rt',294  'filepath': '/home/jeremie/miniforge/envs/flexiblas_threadpoolctl/lib/libmkl_rt.so.2',295  'version': '2024.0-Product',296  'threading_layer': 'gnu'}]297```298 299You can observe that the previously linked OpenBLAS shared object stays loaded by300the Python program indefinitely, but FlexiBLAS itself no longer delegates BLAS calls301to OpenBLAS as indicated by the `current_backend` attribute.302### Writing a custom library controller303 304Currently, `threadpoolctl` has support for `OpenMP` and the main `BLAS` libraries.305However it can also be used to control the threadpool of other native libraries,306provided that they expose an API to get and set the limit on the number of threads.307For that, one must implement a controller for this library and register it to308`threadpoolctl`.309 310A custom controller must be a subclass of the `LibController` class and implement311the attributes and methods described in the docstring of `LibController`. Then this312new controller class must be registered using the `threadpoolctl.register` function.313An complete example can be found [here](314  https://github.com/joblib/threadpoolctl/blob/master/tests/_pyMylib/__init__.py).315 316### Sequential BLAS within OpenMP parallel region317 318When one wants to have sequential BLAS calls within an OpenMP parallel region, it's319safer to set `limits="sequential_blas_under_openmp"` since setting `limits=1` and320`user_api="blas"` might not lead to the expected behavior in some configurations321(e.g. OpenBLAS with the OpenMP threading layer322https://github.com/xianyi/OpenBLAS/issues/2985).323 324### Known Limitations325 326- `threadpool_limits` can fail to limit the number of inner threads when nesting327  parallel loops managed by distinct OpenMP runtime implementations (for instance328  libgomp from GCC and libomp from clang/llvm or libiomp from ICC).329 330  See the `test_openmp_nesting` function in [tests/test_threadpoolctl.py](331  https://github.com/joblib/threadpoolctl/blob/master/tests/test_threadpoolctl.py)332  for an example. More information can be found at:333  https://github.com/jeremiedbb/Nested_OpenMP334 335  Note however that this problem does not happen when `threadpool_limits` is336  used to limit the number of threads used internally by BLAS calls that are337  themselves nested under OpenMP parallel loops. `threadpool_limits` works as338  expected, even if the inner BLAS implementation relies on a distinct OpenMP339  implementation.340 341- Using Intel OpenMP (ICC) and LLVM OpenMP (clang) in the same Python program342  under Linux is known to cause problems. See the following guide for more details343  and workarounds:344  https://github.com/joblib/threadpoolctl/blob/master/multiple_openmp.md345 346- Setting the maximum number of threads of the OpenMP and BLAS libraries has a global347  effect and impacts the whole Python process. There is no thread level isolation as348  these libraries do not offer thread-local APIs to configure the number of threads to349  use in nested parallel calls.350 351 352## Maintainers353 354To make a release:355 356- Bump the version number (`__version__`) in `threadpoolctl.py` and update the357  release date in `CHANGES.md`.358 359- Build the distribution archives:360 361```bash362pip install flit363flit build364```365 366and check the contents of `dist/`.367 368- If everything is fine, make a commit for the release, tag it and push the369tag to github:370 371```bash372git tag -a X.Y.Z373git push git@github.com:joblib/threadpoolctl.git X.Y.Z374```375 376- Upload the wheels and source distribution to PyPI using flit. Since PyPI doesn't377  allow password authentication anymore, the username needs to be changed to the378  generic name `__token__`:379 380```bash381FLIT_USERNAME=__token__ flit publish382```383 384  and a PyPI token has to be passed in place of the password.385 386- 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).387 388- Publish the release on github.389 390### Credits391 392The initial dynamic library introspection code was written by @anton-malakhov393for the smp package available at https://github.com/IntelPython/smp .394 395threadpoolctl extends this for other operating systems. Contrary to smp,396threadpoolctl does not attempt to limit the size of Python multiprocessing397pools (threads or processes) or set operating system-level CPU affinity398constraints: threadpoolctl only interacts with native libraries via their399public runtime APIs.400 401 
Aluode/PerceptionLabPortable · CoolFace