python / python/cpython

Optimize int add/sub for wide exact ints

オープン
#151,289 コメント 6 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

interpreter-core performance type-feature
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

CPython has a fast path for compact integers in binary add/sub, but wide exact ints still go through the generic long arithmetic path even when both operands fit in int64_t.

This issue proposes adding a separate fast path for exact PyLong operands that fit in signed 64-bit integers, while preserving the existing compact-int path.

Suggested implementation:

  • Keep the current compact-int specialization unchanged.
  • Add a separate wide-int path for exact ints that fit in int64_t.
  • Preserve current behavior for overflow, subclasses, and other non-exact-int cases.

Motivation:

  • Improve performance for wide integer add/sub without affecting the common compact-int hot path.
  • Avoid adding new opcodes in the compact-int path.
  • Fit within the current interpreter and specialization structure.

Benchmark evidence:

  • I prototyped this locally with a benchmark covering compact and wide add/sub cases.
  • Wide cases improved substantially, while compact cases remained effectively flat.
  • Representative interpreter-only results with JIT disabled:
    • add_wide: about 25% faster
    • sub_wide: about 35% faster
    • add_compact/sub_compact: effectively unchanged

Benchmark script used locally:

"""Microbenchmark compact vs wide int add/sub with pyperf.

Use this with PYTHON_JIT=0 and -S if you want a stable interpreter-only run:

    PYTHON_JIT=0 ./python.exe -S Tools/scripts/bench_wide_int_pyperf.py
"""

from __future__ import annotations

import pyperf


def bench_add_compact() -> int:
    a = 1
    b = 2
    return a + b


def bench_add_wide() -> int:
    a = 10_000_000_000
    b = 1
    return a + b


def bench_sub_compact() -> int:
    a = 1
    b = 2
    return a - b


def bench_sub_wide() -> int:
    a = 10_000_000_000
    b = 1
    return a - b


def main() -> None:
    runner = pyperf.Runner()
    runner.bench_func("add_compact", bench_add_compact)
    runner.bench_func("add_wide", bench_add_wide)
    runner.bench_func("sub_compact", bench_sub_compact)
    runner.bench_func("sub_wide", bench_sub_wide)


if __name__ == "__main__":
    main()
Linked PRs
  • gh-151290

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まずリンクされている PR gh-151290 を確認し、続いて issue で説明されているインタープリターの特殊化構造を調べてください。PYTHON_JIT=0 と -S を指定して Tools/scripts/bench_wide_int_pyperf.py を実行し、compact と wide の add/sub ケースを比較してください。wide で int64-compatible なオペランドが fast path を使用し、compact、overflow、subclass、non-exact-int の動作が変わらない状態になれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
performance
issue の種類
リファクタリング
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。