Cython

aus Wikipedia, der freien Enzyklopädie
Cython
Paradigmen: multiparadigmatisch
Entwickler: Robert Bradshaw, Stefan Behnel, et al.
Typisierung: stark, statisch, dynamisch („Duck-Typing“)
Beeinflusst von: Python, C, C++
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

Cython basiert auf Pyrex von Greg Ewing (Erstveröffentlichung am 4. April 2002[1]). 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.

Namensherkunft

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

Ziele

Das Cython-Projekt hat sich zum Ziel gesetzt, einen Compiler für normalen Python-Code zu entwickeln,[2] 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.

Eigenschaften

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[3], 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).

Performance

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.[4] 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.[5] Im Vergleich dazu liegt die typische Beschleunigung durch den Python-JIT-Compiler Psyco bei etwa vier- bis hundertfach,[6] bei PyPy in ausgewählten Fällen bei bis zu zwölffach.[7]

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.[8][9]

Anwendungsgebiete

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.[10]

Verwandte und ähnliche Projekte

  • 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

  1. ursprüngliche Versionen des Vorgängers Pyrex
  2. Kompatibilität zu Python 2 ist erklärtes Ziel für die zukünftige Cython-Version 1.0 (Memento des Originals vom 10. August 2011 im Internet Archive)  Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/wiki.cython.org
  3. Slices auf docs.python.org, abgerufen am 2. August 2018
  4. gmane.comp.python.cython.devel – pybench-Vergleich von Cython und CPython 2.6.2
  5. gmane.comp.python.cython.devel – Passing a pointer from Python (Memento des Originals vom 14. Februar 2017 im Internet Archive)  Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/thread.gmane.org
  6. Psyco – Introduction
  7. Geschwindigkeit von PyPy 1.4 im Vergleich zu CPython 2.6.2 mit/ohne Psyco
  8. C++-Wrapper-Benchmarks für verschiedene Python-Wrapper-Generatoren (ohne Cython) (Memento des Originals vom 4. April 2015 im Internet Archive)  Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/telecom.inescporto.pt
  9. C++-Wrapper-Benchmarks für Cython, Boost.Python und PyBindGen
  10. Liste der in Cython implementierten Python-Pakete auf PyPI