Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

`threadpool_limits` is not thread-safe under `ThreadPoolExecutor`

Đang mở
#205 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
48/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
numpy, python, pytorch
Lĩnh vực
backend, performance

Hướng nghiên cứu

Start by reading the threadpool_limits context manager and its tests; the issue does not name their file paths. Reproduce the reported behavior with the supplied ThreadPoolExecutor example and inspect how limits are changed and restored across overlapping contexts. Done means concurrent workers consistently observe the intended limit and the original limits are restored afterward.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

When using threadpoolctl.threadpool_limits inside multiple Python threads (e.g. via ThreadPoolExecutor), the thread limit is not reliably enforced.
Despite using with threadpool_limits(limits=2) inside each worker, some threads observe OpenBLAS using the full default thread count.

Reproducible Example

#!/usr/bin/env python3
from threadpoolctl import threadpool_limits, threadpool_info
import torch

from concurrent.futures import ThreadPoolExecutor, as_completed


def worker(i):
    # NOTE: this appears to be process-global, not thread-local
    with threadpool_limits(limits=2):
        a = torch.randn(512, 256, device="cpu")
        b = torch.randn(256, 512, device="cpu")
        _ = a @ b
        info = threadpool_info()
        print(f"[worker {i}] threadpool_info:", info)
        return info


results = []

with ThreadPoolExecutor(max_workers=8) as executor:
    futures = [executor.submit(worker, i) for i in range(8)]
    for fut in as_completed(futures):
        results.append(fut.result())

print("final threadpool_info:")
print(threadpool_info())

Actual Output

[worker 6] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 1] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 5] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 24, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 3] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 4] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 0] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 7] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
[worker 2] threadpool_info: [{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 2, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]
final threadpool_info:
[{'user_api': 'blas', 'internal_api': 'openblas', 'num_threads': 2, 'prefix': 'libscipy_openblas', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-56d6093b.so', 'version': '0.3.29', 'threading_layer': 'pthreads', 'architecture': 'Haswell'}, {'user_api': 'openmp', 'internal_api': 'openmp', 'num_threads': 24, 'prefix': 'libgomp', 'filepath': '/root/miniconda3/envs/gp_py311/lib/python3.11/site-packages/torch/lib/libgomp.so.1', 'version': None}]

Some workers correctly observe num_threads = 2, while others observe num_threads = 24, even though all are wrapped in with threadpool_limits(limits=2).


Environment

Distributor ID: Ubuntu
Description: Ubuntu 22.04.5 LTS
Release: 22.04
Codename: jammy

torch: 2.9.0
numpy: 2.2.6
scipy: 1.16.2
threadpoolctl: 3.6.0

Ngôn ngữ chính
Python
Star
434
Fork
38
Merge trung bình
2 ngày 14 giờ
Pull request đã merge (30 ngày)
8

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của joblib/threadpoolctl

Tất cả issue của joblib/threadpoolctl

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.