Inhalt

Beschleunige Python-Code mit Microsoft Pyjion

Pyjion ist ein Open-Source-Projekt, das die Leistung von Python-Code durch die optimierten JIT-Kompilierungsfunktionen des .NET-Pakets verbessern soll. Mit Pyjion kannst du die Geschwindigkeit von Python-Anwendungen erheblich verbessern. Wir wollen herausfinden, wie du Python-Code optimieren und beschleunigen kannst.

Was ist Pyjion?

Die gängigste Methode, deinen Python-Code zu beschleunigen, ist die Verwendung von CPython, dem offiziellen Python-Interpreter. Er kompiliert Code in eine Zwischensprache namens “Bytecode” und wertet diesen Code aus, wenn dein Code ausgeführt wird. Das ermöglicht viel Flexibilität, hat aber auch einen Nachteil. Einfache Berechnungen, bei denen CPUs sehr effizient sind, wie z. B. die Arithmetik von ganzen Zahlen und Fließkommazahlen, sind in CPython deutlich langsamer als in anderen Interpretern.

In der Praxis verwenden Python-Entwickler/innen Tools wie Cython, um numerische Operationen effizienter zu machen, indem sie den Code mithilfe von C-Erweiterungen vorzeitig kompilieren. Das ist eine effektive Lösung für die Leistung, aber nicht ideal für schnelle Iterationen oder Experimente, besonders in Jupyter-Notebooks.

Hier kommt Pyjion zum Einsatz. Pyjion ist ein Python 3.10-Paket, das Python-Code analysiert und ihn mit einem JIT-Compiler (Just-in-Time) optimiert. Er kann in einem Programm verwendet werden, indem du die Pyjion-Bibliothek importierst und aktivierst. Alles, was nach dieser Anweisung ausgeführt wird, ist JIT-kompiliert.

Wie man es ausspricht

“Pyjion” wird wie das Wort “pigeon” (Taube) ausgesprochen. @DinoV wollte einen Namen, der etwas mit “Python” - dem “Py”-Teil - und etwas mit “JIT” - dem “JI”-Teil - enthält und aussprechbar ist.

Hauptmerkmale

  • Profilgeführter JIT-Compiler
  • Native 64-Bit Float- und Integer-Unterstützung
  • Kleiner, schneller Compiler
  • Windows, macOS und Linux
  • Unterstützung von Intel und ARM CPUs
  • Eingebauter IL- und ASM-Disassembler
  • Unterstützung für native Debugging- und Profiling-Tools

Technologie

Pyjion kompiliert nativen CPython Bytecode in Maschinencode. Ohne Pyjion verwendet CPython eine Master-Evaluierungsschleife (die so genannte Frame-Evaluierungsschleife), um über Opcodes zu iterieren. Der Pyjion-Compiler besteht aus 3 Hauptschritten:

  • Erstellen einer “Stapeltabelle” mit den abstrakten Typen an jeder Opcode-Position
  • Kompilieren der CPython-Opcodes in IL-Anweisungen (ECMA335 CIL)
  • Übergabe der CIL-Opcodes an den .NET EE-Compiler zur Umwandlung in nativen Maschinencode/Assembly

Benchmarks

Die von den Projektbetreuern durchgeführten Benchmarks zeigen, dass Pyjion in der Praxis etwa zwei- bis dreimal schneller ist als normales Python.

Pyjion Benchmarks
Python 3.10 vs Python 3.10 + Pyjion

Einige der Optimierungen ermöglichen Geschwindigkeitssteigerungen von bis zu 10 Mal. Reguläre Arithmetik, immer ein guter Kandidat für eine JIT-Optimierung, kann um eine Größenordnung schneller sein.

Beschränkungen

Einige Python-Funktionen, wie with-Anweisungen oder async..await-Anweisungen sind noch nicht implementiert. Beide sind auf der Roadmap. Pyjion enthält eine Middleware-Schicht, die es WSGI-Anwendungen ermöglicht, unter Pyjion zu laufen. Lang laufende Anwendungen wie Webanwendungen sind gute Kandidaten für die JIT-Beschleunigung.

Installation

Pyjion benötigt:

Nachdem du die Installationsschritte befolgt hast, ist Pyjion nur noch ein Python-Modul, das du in deine Python-Umgebung importieren kannst:

1
python -m pip install pyjion

Nachdem du Pyjion importiert hast, aktiviere das JIT mit der Funktion enable:

1
2
import pyjion
pyjion.enable()

Jeder Python-Code, den du nach der Aktivierung von Pyjion schreibst oder importierst, wird JIT-kompiliert. Du musst die Funktionen nicht in einer speziellen API ausführen, es ist völlig transparent:

1
2
3
4
>>> def half(x):
...    return x/2
>>> half(2)
1.0

Du kannst Pyjion auch gegen jedes Skript oder Modul ausführen:

1
pyjion my_script.py

Oder für ein bestehendes Python-Modul:

1
pyjion -m calendar

Das war’s!

Vergleich

Wie Pyjion im Vergleich zu:

PyPy

Site: https://www.pypy.org/

PyPy ist eine Implementierung von Python mit eigenem JIT. Der größte Unterschied zu Pyjion ist, dass PyPy nicht alle C-Erweiterungsmodule ohne Änderungen unterstützt, es sei denn, sie verwenden CFFI oder arbeiten mit der ausgewählten Teilmenge der C-API von CPython, die PyPy unterstützt. Pyjion zielt außerdem darauf ab, viele JIT-Compiler zu unterstützen, während PyPy nur den eigenen JIT-Compiler unterstützt.

Pyston

Site: https://github.com/pyston/pyston

Pyston ist eine Implementierung von Python, die LLVM als JIT-Compiler verwendet. Im Vergleich zu Pyjion bietet Pyston eine teilweise, aber keine vollständige Unterstützung der CPython C API. Pyston unterstützt auch nur LLVM als JIT-Compiler.

Numba

Site: https://numba.pydata.org/

Numba ist ein JIT-Compiler für “array-orientierten und mathematiklastigen Python-Code”. Das bedeutet, dass Numba auf wissenschaftliche Berechnungen ausgerichtet ist, während Pyjion versucht, den gesamten Python-Code zu optimieren. Numba unterstützt außerdem nur LLVM.

IronPython

Site: https://ironpython.net/

IronPython ist eine Implementierung von Python, die mit .NET umgesetzt wird. Während IronPython versucht, von .NET aus nutzbar zu sein, hat Pyjion keine Kompatibilitätsgeschichte mit .NET. Das bedeutet auch, dass IronPython keine C-Erweiterungsmodule verwenden kann, Pyjion hingegen schon.

Nuitka, Shedskin

Site Nuitka: https://nuitka.net/pages/overview.html

Site Shedskin: https://github.com/shedskin/shedskin

Sowohl Nuitka als auch Shedskin sind Python-zu-C++-Transpiler, das heißt, sie übersetzen Python-Code in entsprechenden C++-Code. Pyjion ist ein JIT und kein Transpiler.