python / python/cpython

Hot-cold splitting in the cases generator and JIT optimizer.

Aperta
#150,712 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

3.16 interpreter-core performance topic-JIT
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

https://github.com/python/cpython/issues/143158 describes hot-cold splitting in the JIT, but that is too late for optimizations that sink code onto exits.

To support those optimizations, we need to split uops as defined into bytecodes.c into "hot" and "cold" ops.

From https://github.com/python/cpython/issues/143158#issuecomment-4544178632

For example, we want to transform this:

        op (_GUARD_IS_NONE_POP, (val -- )) {
            int is_none = PyStackRef_IsNone(val);
            if (!is_none) {
                PyStackRef_CLOSE(val);
                AT_END_EXIT_IF(1);
            }
            DEAD(val);
        }

into this:

        op (_GUARD_IS_NONE_POP, (val -- )) {
            int is_none = PyStackRef_IsNone(val);
            if (!is_none) {
                goto _GUARD_IS_NONE_POP_COLD; // tail call
            }
            DEAD(val);
        }

        op (_GUARD_IS_NONE_POP_COLD, (val -- )) {
            PyStackRef_CLOSE(val);
            AT_END_EXIT_IF(1);
        }

Currently, during lowering of the uop trace to a form suitable for execution we need to insert an _EXIT_TRACE uop as the target for exit jumps in the uop. We want to replace those with the "cold" uop followed by the exit, allowing compensation code to be more easily sunk onto side exits.

While it is appealing to do this automatically, it might make more sense to do the splitting manually, and add support for custom exits to the tooling.

We could mark ops as exit and explicitly state which exit is being used (with _EXIT_TRACE as the default exit).
So _GUARD_IS_NONE_POP would be rewritten as:

        op (_GUARD_IS_NONE_POP, (val -- )) {
            int is_none = PyStackRef_IsNone(val);
            if (!is_none) {
                EXIT_TO(POP_TOP_EXIT);
            }
            DEAD(val);
        }

        exit op (POP_TOP_EXIT, (val -- )) {
            PyStackRef_CLOSE(val);
        }

Likewise, _ITER_NEXT_INLINE would be rewritten as:

    tier2 op(_ITER_NEXT_INLINE, (iternext_fn/4, iter, null_or_index -- iter, null_or_index, next)) {
        assert(sizeof(iternextfunc) == sizeof(uintptr_t));
        volatile iternextfunc iternext_v = (iternextfunc)iternext_fn;
        PyObject *item = iternext_v(PyStackRef_AsPyObjectBorrow(iter));
        if (item == NULL) {
            EXIT_TO(_ITER_NEXT_INLINE_EXIT);
        }
        STAT_INC(FOR_ITER, hit);
        next = PyStackRef_FromPyObjectSteal(item);
    }

    exit op(_ITER_NEXT_INLINE_EXIT, ( -- )) {
        if (_PyErr_Occurred(tstate)) {
            if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {
                _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr);
                _PyErr_Clear(tstate);
            }
            else {
                ERROR_NO_POP();
            }
        }
   }

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia da bytecodes.c e dalla discussione sull’hot-cold splitting nell’issue 143158, quindi traccia come vengono abbassate le uop traces e come gli strumenti rappresentano gli exits. Definisci come le exit ops e i custom exits sostituiscono i target _EXIT_TRACE inseriti e verifica che il codice di compensazione dei side-exits possa essere rappresentato e sottoposto a sinking come previsto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
compilers, performance
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.