Recursive @threadpool_limits.wrap() calls do not behave as expected when recursing

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

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

@itamarst đang làm issue này rồi.

Từ ngày 2/11/2026.

  • #294 của @itamarst — đang mở

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
35/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ệ
python
Lĩnh vực
performance

Hướng nghiên cứu

The failing case is the test test_recursive_wrap_releases_the_shared_pool_claim, which needs a non-OpenMP OpenBLAS build with at least two threads. Start by running it with recurse(1) and reading how threadpool_limits.wrap restores limits and releases the controlling thread on return. Done when the test passes with recurse(1) and the existing recursion behaviour still holds.

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

Mô tả

Returning from a wrapped function should return to the previous level of thread limits at the time they were called, even in the face of recursion. That's not what happens in practice, though.

The following test fails on both master and 3.7 (i.e. it's not due to the controlling thread changes), but passes if recurse(1) is switched to recurse(0).

from threading import Thread

from threadpoolctl import threadpool_limits, ThreadpoolController

import numpy
import pytest

def run_in_thread(f, *args, **kwargs):
    thread = Thread(target=lambda: f(*args, **kwargs))
    thread.start()
    thread.join()
    return thread


def _non_openmp_openblas():
    openblas = ThreadpoolController().select(internal_api="openblas")
    if not openblas:
        pytest.skip("requires OpenBLAS.")
    libs = []
    seen = set()
    for lib in openblas.lib_controllers:
        if lib.threading_layer == "openmp" or lib.filepath in seen:
            continue
        seen.add(lib.filepath)
        libs.append(lib)
    if not libs:
        pytest.skip("require non-OpenMP OpenBLAS.")
    return libs


def _require_resizable_non_openmp_openblas():
    libs = _non_openmp_openblas()
    lib = libs[0]
    orig = lib.get_num_threads()
    if orig is None or orig < 2:
        pytest.skip("Test requires a non-OpenMP OpenBLAS with at least 2 threads")
    return lib, orig


def test_recursive_wrap_releases_the_shared_pool_claim():
    # One wrapped function calling itself must keep the limit between the inner
    # return and the outer return, then restore the original count and drop the
    # controlling thread. Another thread can then set the count.
    lib, orig = _require_resizable_non_openmp_openblas()

    @threadpool_limits.wrap(limits=1, user_api="blas")
    def recurse(depth):
        assert lib.get_num_threads() == 1
        if depth:
            recurse(depth - 1)
            assert lib.get_num_threads() == 1

    recurse(1)
    assert lib.get_num_threads() == orig

    observed = {}

    def other_thread():
        lib.set_num_threads(1)
        observed["threads"] = lib.get_num_threads()

    worker = run_in_thread(other_thread)
    assert observed["threads"] == 1
Ngôn ngữ chính
Python
Star
434
Fork
38
Merge trung bình
1 ngày 5 giờ
Pull request đã merge (30 ngày)
15

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.