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.

Pyjion ist ein Tool, das die Leistung von Python erheblich steigern kann, indem es einen Just-In-Time (JIT) Compiler in die Python-Laufzeitumgebung integriert. In diesem Artikel wird erklärt, wie Pyjion funktioniert und wie Entwickler es nutzen können, um ihren Python-Code zu beschleunigen, ohne große Änderungen an ihren Projekten vorzunehmen. Es ist eine großartige Option für alle, die die Ausführungsgeschwindigkeit von Python optimieren und gleichzeitig die Einfachheit beibehalten möchten.

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.

“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.

  • 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

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

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.

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.

Pyjion benötigt:

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

python -m pip install pyjion

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

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:

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

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

pyjion my_script.py

Oder für ein bestehendes Python-Modul:

pyjion -m calendar

Das war’s!

Wie Pyjion im Vergleich zu:

Site: https://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.

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.

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.

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.

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.