AI-United » Allgemein » Verwenden von Cython zur Beschleunigung des Python-Codes um mehr als das 30-Fache

Verwenden von Cython zur Beschleunigung des Python-Codes um mehr als das 30-Fache

Python ist die derzeit beliebteste Programmiersprache der Welt, gefolgt von C++ und C! Ihr größter Vorteil besteht darin, dass sie bei weitem am einfachsten zu bedienen ist, da der Code auf eine intuitiv und menschenlesbare Weise geschrieben ist. 

Sie hat jedoch einen Nachteil, über den immer wieder gesprochen wird, überwiegend von den C-Code-Gurus: Python ist langsam.

Und dies stimmt.

Verglichen mit anderen allgemein verwendeten Programmiersprachen ist Python wirklich langsam. Dies wurde von Benchmark game bewiesen, das einige solide Benchmarks zur Verfügung stellt, mit denen die Geschwindigkeit einer Reihe von Programmiersprachen für verschiedene Aufgaben verglichen wird.

Zwei der wichtigsten Möglichkeiten, den ganzen Prozess zu beschleunigen, sind:

  1. Einsatz der Multi-Processing-Bibliotheken, die das Verwenden aller CPU-Kerne ermöglichen
  2. Einsatz von Rapids zur Beschleunigung der Verarbeitung auf der GPU bei der Arbeit mit Numpy, Pandas oder Scikit-Learn.

Diese Möglichkeiten sind dann sehr hilfreich, wenn es sich um Parallelisierung der Prozesse handelt wie beispielsweise Datenvorverarbeitung oder Matrixoperationen.

Es gibt jedoch eine Reihe von Fällen, bei denen eine Möglichkeit bestehen sollte, Python selbst zu beschleunigen: Der Code ist reines Python; Es gibt eine große for-Schleife, die nur verwendet werden muss und nicht in eine Matrix eingefügt werden kann, weil es notwendig ist, Daten nacheinander zu verarbeiten. 

In diesen Fällen wird Cython eingesetzt. Neben der Anbindung von externen Bibliotheken an den CPython-Interpreter ist das zweite Haupteinsatzgebiet von Cython die Beschleunigung von rohem Phyton-Code.

Cython: Definition

Im Grunde genommen handelt es sich bei Cython um einen Zwischenschritt zwischen Python und C/C ++. Mit ihrer Hilfe kann der reine Python-Code mit einigen kleinen Änderungen geschrieben und dann direkt in die Zielsprache C übersetzt werden.

Am Python-Code muss nur eine einzige Anpassung vorgenommen werden. Dies ist das Hinzufügen von Typinformationen zu jeder Variablen. In der Regel sieht eine Variable in Python wie folgt aus:

x = 0.5

Nach dem Hinzufügen des Typs mit Cython wird diese Variable auf folgende Weise dargestellt:

cdef float x = 0.5

Ähnlich wie bei C sagt auch Cython, dass die Variable ein Gleitkomma ist. Bei reinem Python wird der Typ der Variablen spontan bestimmt. Durch die explizite Typdeklaration in Cython wird die Konvertierung nach C ermöglicht, da explizite Typdeklarationen + erforderlich sind. 

Um Cython zu installieren, wird nur eine einzige Pip-Zeile benötigt:

pip install cython

Typen in Cython

Man unterscheidet zwei verschiedene Typenreihen für Variablen und Funktionen in Cython.

Typen von Variablen sind:

  • cdef int a, b, c
  • cdef char *s
  • cdef float x = 0.5 (einfache Genauigkeit)
  • cdef double x = 63.4 (doppelte Genauigkeit)
  • cdef list names
  • cdef dict goals_for_each_play
  • cdef object card_deck

Es sollte darauf hingewiesen werden, dass alle diesen Typen aus C/C ++ stammen! 

Typen von Funktionen sind:

  • def — Grundsätzlich ist es Python. def-Funktion wird von Python aus aufgerufen.
  • cdef — Grundsätzlich ist es C. cdef-Funktion wird für Cython-Funktionen verwendet, die reine C-Funktionen sein sollen, und wird von C aus aufgerufen werden.
  • cpdef —kombiniert sowohl def- als auch cdef-Funktion, indem sie zwei Funktionen erstellt: die def-Funktion für den Python-Typ und die cdef-Funktion für den C-Typ. Sie kann also sowohl von Python als auch von C aus aufgerufen werden.

Nachdem man den Überblick über den Begriff und Typen in Cython bekommen hat, kann man fortfahren und die Beschleunigung implementieren!

Beschleunigung des Codes mit Cython

Der erste Schritt besteht darin, einen Python-Code-Benchmark einzurichten: Eine for-Schleife wird verwendet, um die Fakultät einer Zahl zu berechnen. Nachfolgend wird der rohe Python-Code dargestellt:

def test(x):
    y = 1
    for i in range(1, x+1):
        y *= i
    return y

Beachten Sie, dass der Cython-Äquivalent mit der gleichen Funktion auf ähnliche Weise dargestellt wird. Zunächst ist es jedoch notwendig, sicherzustellen, dass die Cython-Codedatei die Erweiterung .pyx hat. Die einzige Änderung wird am Code selbst vorgenommen, und zwar wird der Typ jeder Variablen und Funktion deklariert.

cpdef int test(int x):
    cdef int y = 1
    cdef int i
    for i in range(1, x+1):
        y *= i
    return y

Darüber hinaus muss man darauf achten, dass die Funktion cpdef verwendet wird, um sicherzustellen, dass sie von Python aus aufgerufen werden kann. Beachten Sie auch, wie sogar die Loop-Variable i einen Typ hat. Für alle Variablen in der Funktion muss der Typ festgelegt werden, was dem C-Compiler erleichtert zu verstehen, welchen Typ er verwenden soll!

Beim nächsten Schritt wird eine setup.py-Datei erstellt, deren Aufgabe es ist, den Cython-Code in C-Code zu kompilieren:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('run_cython.pyx'))

Dann wird das Kompilieren durchgeführt:

python setup.py build_ext --inplace

Man hat ein fertiges Ergebnis: Der C-Code wurde erfolgreich kompiliert und ist einsatzbereit!

Man kann sehen, dass sich im Ordner mit dem Cython-Code alle zum Ausführen von C-Code notwendigen Dateien befinden, darunter die run_cython.c -Datei. Bei Interesse kann man einen Blick darauf werfen, um den C-Code zu sehen, den Cython generiert hat!

Der neue, superschnelle C-Code ist fertig und kann getestet werden! Der nachfolgende Code implementiert einen Geschwindigkeitstest, mit dem der Python-Code mit dem Cython-Code verglichen werden kann.

import run_python
import run_cython
import time

number = 10

start = time.time()
run_python.test(number)
end =  time.time()

py_time = end - start
print("Python time = {}".format(py_time))

start = time.time()
run_cython.test(number)
end =  time.time()

cy_time = end - start
print("Cython time = {}".format(cy_time))

print("Speedup = {}".format(py_time / cy_time))

Wie man sieht ist der Code sehr einfach. Auf die gleiche Weise wie beim regulären Python werden die Dateien importiert und die Funktionen ausgeführt!

Cython liefert gute Möglichkeiten zur Beschleunigung für fast jeden  rohen Python-Code, ohne dass viel zusätzlicher Aufwand benötigt wird. Das Wichtigste ist, dass je mehr Schleifen man durchläuft und je mehr Daten man verarbeitet, desto besser kann Cython helfen.

Die nachfolgende Tabelle zeigt, wie viel Geschwindigkeit Cython für verschiedene Fakultätswerte gegeben hat. Mit Cython kann man über 36-fache Geschwindigkeitsbeschleunigung erreichen!

Number Python Time Cython Times Speedup
10 1.6689300537109375e-06 4.76837158203125e-07 3.5
100 3.337860107421875e-06 4.76837158203125e-07 7.0
1000 2.193450927734375e-05 9.5367431640625e-07 23.0
10000 0.0002090930938720703 6.4373016357421875e-06 32.481
100000 0.0021562576293945312 6.008148193359375e-05 35.89
1000000 0.02128767967224121 0.0005953311920166016 35.75
10000000 0.2148280143737793 0.00594782829284668 36.1187317112278

Sollten Sie weitere Fragen zu Cython haben, so können Sie sich an das Team von AI-United.de per Mail oder Q&A wenden.

Quelle
AI-United-Redaktion

Kommentar hinzufügen

Your email address will not be published. Required fields are marked *

300-101   400-101   300-320   300-070   300-206   200-310   300-135   300-208   810-403   400-050   640-916   642-997   300-209   400-201   200-355   352-001   642-999   350-080   MB2-712   400-051   C2150-606   1Z0-434   1Z0-146   C2090-919   C9560-655   642-64   100-101   CQE   CSSLP   200-125   210-060   210-065   210-260   220-801   220-802   220-901   220-902   2V0-620   2V0-621   2V0-621D   300-075   300-115   AWS-SYSOPS   640-692   640-911   1Z0-144   1z0-434   1Z0-803   1Z0-804   000-089   000-105   70-246   70-270   70-346   70-347   70-410