Cython

Cython
Paradigmen: multiparadigmatisch
Erscheinungsjahr: 28. Juli 2007
Entwickler: Robert Bradshaw, Stefan Behnel, et al.
Aktuelle Version 3.0.11-1[1] (5. August 2024)
Typisierung: stark, statisch, dynamisch („Duck-Typing“)
Beeinflusst von: Python, C, C++
Betriebssystem: Linux, Unix-ähnliches System, Microsoft Windows[2], macOS[2]
Lizenz: Apache-Lizenz, Version 2.0[3], Apache-Lizenz[4]
cython.org

Cython ist eine universelle Programmiersprache, die weitgehend mit Python kompatibel ist. Wie diese unterstützt sie verschiedene Programmierparadigmen wie objektorientierte, aspektorientierte und funktionale Programmierung. Der Hauptvorteil liegt jedoch in der Übersetzung in die Zielsprache C, was sowohl eine hohe Performance im Vergleich zum Standard-Python-Interpreter erlaubt, als auch eine direkte Interaktion mit externem Code ermöglicht, der in C, C++ oder Fortran geschrieben ist.

Haupteinsatzgebiete sind die Anbindung von externen Bibliotheken an den CPython-Interpreter, sowie die Beschleunigung von Python-Code. Der Cython-Compiler kann auch zur Kompilierung reiner Python-Module verwendet werden.

Der generierte Code ist nicht autark, sondern benötigt eine CPython-kompatible Laufzeitumgebung. Dabei wird sowohl die Generierung von Binärmodulen („Extension-Modul“) unterstützt, die dynamisch über den import-Befehl in den Python-Interpreter geladen werden können, als auch die Linker-Integration des CPython-Interpreters in das generierte Modul, so dass ein ausführbares Programm entsteht (Embedding).

Entwicklungsgeschichte

[Bearbeiten | Quelltext bearbeiten]

Cython basiert auf Pyrex von Greg Ewing (Erstveröffentlichung am 4. April 2002[5]). Im Juli 2007 wurde der Cython-Compiler durch Robert Bradshaw und Stefan Behnel als eigenständiges, offen entwickeltes Projekt von Pyrex abgespalten. Seither wurde versucht, die beiden Compiler weitgehend kompatibel zu halten, wobei jedoch Cython wesentlich weiterreichende Optimierungen anwendet und eine höhere Kompatibilität mit Python-Code erreicht. Wichtige Unterschiede zu Pyrex sind in der Cython-Dokumentation beschrieben.

Der Name Cython ist ein Kofferwort der beiden zugrunde liegenden Programmiersprachen: Python und C.

Das Cython-Projekt hat sich zum Ziel gesetzt, einen Compiler für normalen Python-Code zu entwickeln,[6] der durch zusätzliche (explizite) statische Typisierung eine möglichst hohe Performance und eine weitreichende Integration mit Code bietet, der in C, C++ und Fortran geschrieben ist.

Cython ist ein optimierender Compiler, jedoch nicht im gängigen Sinne eines Compilers, der Binärcode erzeugt. Vielmehr erlaubt es die Übersetzung in C-Code, viele grundlegende Optimierungen und Plattform-Anpassungen einem C-Compiler zu überlassen. So kann sich der Cython-Compiler selbst auf High-Level-Optimierungen auf AST-Ebene beschränken.

Der C-Code, den Cython generiert, ist weitgehend portabel bezüglich Plattformen (Prozessor, C-Compiler und Betriebssystem) und CPython-Versionen. Aktuell (Version 0.28.5) werden die CPython-Versionen 2.6 und 2.7 sowie alle von 3.3 an unterstützt. Getestete Plattformen sind unter anderem macOS, Windows und vor allem verschiedene Linux-Distributionen, mit 32-Bit- und 64-Bit-Systemversionen.

Die Kombination von Python und C erlaubt Cython ein sehr breites Anforderungsspektrum abzubilden. Möglich ist sowohl High-Level-Programmierung mit Python-Datentypen, -Sprachkonstrukten und automatischer Speicherverwaltung, als auch eine sehr C-nahe Programmierung mit C-Datentypen, C-Funktionen und manueller Speicherverwaltung. Beides kann beliebig kombiniert werden und die Interaktion mit reinem (unkompilierten) Python-Code ist ebenso nativ möglich wie die Interaktion mit C- oder C++-Code, was bei der Optimierung von Cython-Code ein sehr feingranulares Vorgehen ermöglicht. Beliebige Teile des Codes können in reinem Python geschrieben, mit Cython kompiliert, mit statischen Datentypen optimiert oder sogar nach C portiert werden, je nach Anforderung. Dadurch unterstützt Cython sehr gut das Prinzip, dass der größte Teil der Laufzeit eines Programms in einem sehr kleinen Teil des Quelltextes entsteht, also die Optimierung eines kleinen Programmteils einen sehr großen Performancegewinn bringen kann, während bei dem größten Teil des Codes eine hohe Entwicklungsgeschwindigkeit und ein geringer Wartungsaufwand wichtiger sind als eine größtmögliche Ausführungsgeschwindigkeit.

Die Programmiersprache erreicht die Sprachintegration zwischen Python und C vor allem über Datentypen. So können verschiedene Python-Sprachkonstrukte sowohl auf Python-Datentypen als auch auf C-Datentypen angewendet werden. Ein Beispiel ist die 'for'-Schleife, die in Python eine Foreach-Schleife ist, also über beliebige iterierbare Container laufen kann (z. B. Listen oder Dateien). In Cython kann diese Schleife zudem über C++-Listen, C-Arrays und Teilarrays laufen, sowie über Pointer-Abschnitte (Slices[7], z. B. ptr[2:8] für die Offsets 2–7). Daneben erfolgt eine automatische Konvertierung zwischen verschiedenen Python-Datentypen und C-Datentypen, sowohl bei Skalartypen (Zahlen) als auch bei Zeichenketten und strukturierten Datentypen (z. B. C-Struct-Typen und Python-Dictionaries).

Viele der Optimierungen, die der Cython-Compiler automatisch durchführt, bewirken eine Spezialisierung des generierten C-Codes. Dazu verwendet der Compiler explizite statische Typdeklarationen und (einfache) Typinferenz, um spezialisierten C-Code für die verwendeten Datentypen und bestimmte Code-Patterns zu erzeugen. Ein großer Teil der Optimierungen im Cython-Compiler bezieht sich auf Schleifen, da sich hier zumeist ein großer Teil der Gesamtlaufzeit ansammelt.

Kontrollstrukturen (vor allem Schleifen) sind mit Cython und einem C-Compiler übersetzt um ein Vielfaches schneller, als wenn sie von CPython interpretiert werden.[8] Dies ist bedingt durch optimistische Optimierungen und Typ-Inferenz. Dadurch läuft Cython-kompilierter Python-Code auch ohne explizite Typ-Deklarationen meist schneller als in CPython 2.6.x, obwohl die relative Performance natürlich vom jeweiligen Code abhängt. Durch die statische Deklaration von Datentypen und die dadurch resultierende Spezialisierung des C-Codes lässt sich jedoch zumeist eine Beschleunigung um ein Vielfaches erreichen. Vor allem bei mathematischen Berechnungen ergeben sich oft Laufzeitverbesserungen um den Faktor hundert bis tausend.[9] Im Vergleich dazu liegt die typische Beschleunigung durch den Python-JIT-Compiler Psyco bei etwa vier- bis hundertfach,[10] bei PyPy in ausgewählten Fällen bei bis zu zwölffach.[11]

Der von Cython für Funktionen generierte Code ist optimiert für schnelles Entpacken und Konvertieren von Aufrufparametern. Daher ist ein Python-Aufruf von nativem Code durch einen Cython-Wrapper hindurch im Allgemeinen schneller als in anderen Wrapper-Implementierungen für Python.[12][13]

Anwendungsgebiete

[Bearbeiten | Quelltext bearbeiten]

Die wichtigsten Anwendungsgebiete von Cython sind die Anbindung von externen Bibliotheken an den CPython-Interpreter, sowie die Beschleunigung von Python-Code, insbesondere in mathematischen Berechnungen und rechenintensiven Algorithmen.

Beispielsweise basiert das Computeralgebrasystem SageMath zu einem großen Teil auf Cython-Code. Dieser dient sowohl zur Implementierung mathematischer Algorithmen, als auch zur Anbindung externen Codes in C, C++ und Fortran. Cython unterstützt zudem eine sehr effiziente Interaktion mit NumPy-Matrizen, was darauf basierende Berechnungen stark vereinfacht.

Die High-Performance-XML-Bibliothek lxml ist größtenteils in Cython implementiert. Dabei werden die externen C-Bibliotheken libxml2 und libxslt an den Python-Interpreter angebunden.

Ein weiteres Beispiel aus dem Umfeld der Cython-Core-Entwickler ist die MPI-Bibliothek mpi4py. Sie bindet verschiedene MPI-Implementierungen an CPython an.

Im Python-Package-Index findet sich eine kurze Liste weiterer Bibliotheken, die in Cython implementiert sind.[14]

Verwandte und ähnliche Projekte

[Bearbeiten | Quelltext bearbeiten]
  • Pyrex – Vorgänger von Cython
  • Unladen Swallow – optimierte CPython-Laufzeitumgebung; basiert auf LLVM
  • PyPy – JIT-Compiler-Framework und Python-Laufzeitumgebung, die selbst in einem Python-Dialekt (RPython) geschrieben ist
  • Psyco – spezialisierender JIT-Compiler und Code-Optimierer für die CPython-Laufzeitumgebung
  • Shed Skin – statisch typisierte, Python-ähnliche Programmiersprache, die nach C++ kompiliert wird

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. Release 3.0.11-1. 5. August 2024 (abgerufen am 22. August 2024).
  2. a b docs.cython.org.
  3. github.com. (abgerufen am 2. Februar 2020).
  4. Cython: C-Extensions for Python. (abgerufen am 8. Juli 2018).
  5. ursprüngliche Versionen des Vorgängers Pyrex
  6. Kompatibilität zu Python 2 ist erklärtes Ziel für die zukünftige Cython-Version 1.0 (Memento vom 10. August 2011 im Internet Archive). Abgerufen am 1. April 2024.
  7. Slices auf docs.python.org, abgerufen am 2. August 2018
  8. gmane.comp.python.cython.devel – pybench-Vergleich von Cython und CPython 2.6.2
  9. gmane.comp.python.cython.devel – Passing a pointer from Python (Memento vom 14. Februar 2017 im Internet Archive). Abgerufen am 1. April 2024.
  10. Psyco – Introduction
  11. Geschwindigkeit von PyPy 1.4 im Vergleich zu CPython 2.6.2 mit/ohne Psyco
  12. C++-Wrapper-Benchmarks für verschiedene Python-Wrapper-Generatoren (ohne Cython) (Memento vom 4. April 2015 im Internet Archive). Abgerufen am 1. April 2024.
  13. C++-Wrapper-Benchmarks für Cython, Boost.Python und PyBindGen
  14. Liste der in Cython implementierten Python-Pakete auf PyPI