python / python/cpython

`unpack_sequence` benchmark runs slower under JIT

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

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

performance topic-JIT
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

Bug report

Bug description:

The pyperformance unpack_sequence benchmark is the worst-performing JIT benchmark on https://www.doesjitgobrrr.com — geomean speedup 0.586× (JIT ~1.7× slower).

The benchmark is a single function with 400 inlined a,b,c,d,e,f,g,h,i,j = to_unpack statements inside a for loop. to_unpack = tuple(range(10)) is reused (refcount > 1, so _UNPACK_SEQUENCE_UNIQUE_TUPLE never fires).

Analysis of the slowdown

The JIT covers all 400 unpacks via ~22 sequential traces (~775 uops, ~19 unpacks each), linked tail-to-tail through _EXIT_TRACE → _START_EXECUTOR, totalling ~18 MB of JIT code. This is a consequence of trace length / fitness limits ([UOP_MAX_TRACE_LENGTH] https://github.com/python/cpython/blob/main/Include/internal/pycore_uop.h#L42), EXIT_QUALITY_* from gh-146073) and is arguably fine - 400 inline statements isn't realistic code. Inter-trace transition cost alone would not produce a 1.7× slowdown. Nevertheless, longer traces would help here.

Per unpack: ~33 uops vs tier 1's ~12 bytecodes — ~2.7× more dispatches. The trace recorder unconditionally emits a _CHECK_VALIDITY + _SET_IP pair before every source bytecode at Python/optimizer.c:902-906. Per unpack:

LOAD_FAST_BORROW t            (1)
UNPACK_SEQUENCE 10            (1)
STORE_FAST_STORE_FAST × 5     (5; pair-fused by the compiler)
                              ── 7 source bytecodes → 6 _CHECK_VALIDITY+_SET_IP pairs steady state

Tier 1 has no analog. Each _CHECK_VALIDITY issues a load+branch on current_executor->vm_data.valid; each _SET_IP issues a store to frame->instr_ptr. 12 such uops × 400 unpacks × 20000 iterations is the bulk of the regression.

A naive elimination pass cannot drop them because every gap contains at least one uop with HAS_ESCAPES_FLAG — typically _POP_TOP, conservatively flagged as escaping (its Py_DECREF could run __del__).

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

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.

Hướng nghiên cứu

Bắt đầu bằng cách tái hiện kết quả của pyperformance unpack_sequence và đọc logic của bộ ghi trace trong Python/optimizer.c quanh các dòng 902-906. Xem xét UOP_MAX_TRACE_LENGTH trong Include/internal/pycore_uop.h và kiểm tra các trace được tạo cùng các kiểm tra tính hợp lệ được mô tả trong báo cáo. Issue không xác định một bản sửa cụ thể hoặc bài kiểm tra chấp nhận nào, vì vậy hãy xác nhận tối ưu hóa dự kiến và các tiêu chí thành công dựa trên benchmark trước khi thay đổi mã.

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

Đánh giá

Công nghệ
python
Lĩnh vực
compilers, performance
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Cần làm rõ
Mức phù hợp với người mới
42/100

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.