Dieser Artikel ist eine Fortsetzung von "Einführung in Cython ohne Tiefe".
Beginnen wir mit Cython, um diesmal nicht zu tief zu gehen. Der Zweck dieses Artikels ist nicht, darauf einzugehen, sondern den köstlichen Teil von Cython zu genießen.
Die Cython-Notation ist nicht allzu schwierig. Ich habe einen guten Beispielcode im Cython-Tutorial, also leihen wir ihn uns aus.
Code vor der Optimierung
def myfunction(x, y=2):
a = x - y
return a + x * y
def _helper(a):
return a + 1
class A:
def __init__(self, b=0):
self.a = 3
self.b = b
self._scale = 2.0
self.read_only = 1.0
def foo(self, x):
return x + _helper(1.0)
Wenn Sie den obigen Code mit Cython optimieren, sieht er folgendermaßen aus.
Cython-Optimierungscode
%%cython
cpdef int myfunction(int x, int y=2):
cdef int a = x - y
return a + x * y
cdef double _helper(double a):
return a + 1
cdef class A:
cdef public int x
cdef public int y
cdef double _scale
cdef readonly float read_only
def __init__(self, int b=0):
self.a = 3
self.b = b
self._scale = 2.0
self.read_only = 1.0
cpdef double foo(self, double x):
return (x + _helper(1.0)) * self._scale
Sie können sehen, wie Variablen, Argumente und Rückgabewerte eingegeben werden, indem Sie sie betrachten. Daher ist es nicht erforderlich, sie zu erklären.
Wenn Sie sich die Funktionsdeklarationen genau ansehen, wird die Funktion myfunction durch cpdef
und die Funktion _helper durch cdef
definiert. Die Liste der Funktionsdeklarationen lautet wie folgt.
Erklärung | Erläuterung |
---|---|
def | Langsam, kann von Python aus aufgerufen werden |
cdef | Schnell, nicht über Python aufrufbar, nur in Cython verfügbar |
cpdef | Eine Mischung aus def und cdef, def beim Aufruf von Python, cdef beim Aufruf von Cython |
Wenn Sie in der Klassendeklaration "cdef class A" festlegen, wird diese zu einer cdef-Klasse. Die cdef-Klasse verfügt über eine gute Speichereffizienz und einen schnellen Zugriff, da sie von einer Struktur verwaltet wird, im Vergleich zu der normalen Klasse, die Attribute nach Diktat verwaltet. Sie unterliegt jedoch den folgenden Einschränkungen.
--Dynamische Methoden / Mitglieder können nicht hinzugefügt werden
Die Elementdefinition muss im Voraus wie folgt definiert werden.
cdef class A:
cdef public int x
cdef public int y
cdef double _scale
cdef readonly float read_only
...
Verweise von Python sind nur möglich, wenn public wie das Mitglied _scale hinzugefügt wird. Wenn Sie das Attribut "readonly" wie das Mitglied "read_only" hinzufügen, können Sie es auch nicht in Python ändern.
a = A()
a._scale #Error
a.read_only = 2.0 #Error
Erweiterung | Erläuterung |
---|---|
.pyx | Stellen Sie sich das als Implementierungsdatei oder als Programm selbst vor |
.pxd | Definitionsdatei |
.pxi | Datei einschließen |
Wenn Sie das oben Genannte kennen, werden Sie keine Probleme haben.
Als Prozedur zum Beschleunigen eines Python-Programms ist es eine allgemeine Prozedur, dem ursprünglichen Programm eine Typdefinition hinzuzufügen. Schlagen wir also einen anderen Ansatz vor, nämlich den "reinen Python-Modus".
Lassen Sie uns das obige Beispiel im reinen Python-Modus umschreiben.
pure_Beispiel im Python-Modus neu geschrieben
%%cython
import cython
@cython.ccall
@cython.locals(x=cython.int, y=cython.int)
@cython.returns(cython.int)
def myfunction(x, y=2):
a = x-y
return a + x * y
@cython.cfunc
@cython.locals(a=cython.double)
@cython.returns(cython.double)
def _helper(a):
return a + 1
@cython.cclass
class A:
a = cython.declare(cython.int, visibility='public')
b = cython.declare(cython.int, visibility='public')
_scale = cython.declare(cython.double)
read_only = cython.declare(cython.double, visibility="readonly")
@cython.locals(b=cython.int)
def __init__(self, b=0):
self.a = 3
self.b = b
self._scale = 2.0
self.read_only = 1.0
@cython.ccall
@cython.locals(x=cython.double)
@cython.returns(cython.double)
def foo(self, x):
return x + _helper(1.0) * self._scale
Es ist ein Stil, bei dem "Cython importieren" in Python-Code ausgeführt wird und Typinformationen durch Dekorieren hinzugefügt werden. Jetzt können Sie dieselbe Datei in Python ausführen und in Cython kompilieren.
Da die Typinformationen außerhalb der Funktion definiert sind, muss der Python-Codeteil innerhalb der Funktion überhaupt nicht geändert werden. Die Lesbarkeit des Verarbeitungsteils bleibt gleich, so dass es überraschend angenehm ist, wenn Sie sich an den Sturm der Dekorateure gewöhnen.
Einzelheiten zum reinen Python-Modus von Cython finden Sie in der offiziellen Dokumentation. Es handelt sich um ein kurzes Tutorial, das leicht zu lesen ist, da fast kein englischer Text vorhanden ist.
http://cython.readthedocs.io/en/latest/src/tutorial/pure.html
Sie können den Code in der Funktion wie im reinen Python-Modus beschleunigen, aber Sie können die .pxd-Datei verwenden, um die gesamte .py-Datei zu beschleunigen, ohne sie zu ändern.
Diese Erklärung ist ein kurzer Auszug aus dem offiziellen Handbuch.
http://omake.accense.com/static/doc-ja/cython/src/tutorial/pure.html
Wenn eine .pxd-Datei mit demselben Namen wie die> .py-Datei gefunden wird, sucht Cython nach cdefed-Klassen und cdef / cpdefed-Funktionen und -Methoden. Konvertieren Sie dann die entsprechenden Klassen / Funktionen / Methoden in .py in die entsprechenden Typen. Daher, wenn es a.pxd wie unten gibt:
cdef class A:
cpdef foo(self, int i)
Zur gleichen Zeit, wenn Sie eine Datei namens a.py wie die folgende haben:
class A:
def foo(self, i):
print "Big" if i > 1000 else "Small"
Der Code wird wie folgt interpretiert:
cdef class A:
cpdef foo(self, int i):
print "Big" if i > 1000 else "Small"
Wenn Sie sich den Code im reinen Python-Modus genauer ansehen, sehen Sie [PyCharm Type Hinting](http://qiita.com/pashango2/items/de342abc10722ed7a569#%E5%BC%B7%E5%8A%9B%E3%81%AA% E3% 82% BF% E3% 82% A4% E3% 83% 97% E3% 83% 92% E3% 83% B3% E3% 83% 86% E3% 82% A3% E3% 83% B3% E3% Ähnlich wie 82% B0). Ich verwende häufig die Typhinweise von PyCharm, daher fand ich den reinen Python-Modus einfach zu bedienen.
Beispiel für einen PyCharm-Typ
class A:
"""
:type a: int
:type b: int
"""
def __init__(self, b=0):
"""
:type b: int
"""
self.a = 3
self.b = b
def foo(self, x):
"""
:type x: float
:rtype: float
"""
return x * float(self.a)
Außerdem verfügt Python über eine Stub-Datei (.pyi), die nur Typinformationen enthält.
https://www.python.org/dev/peps/pep-0484/#stub-files
Die Stub-Datei ist der am Ende beschriebenen "agumenting.pxd-Datei" sehr ähnlich.
In Zukunft wird Python-Code mit Typhinweisen oder Typanmerkungen von Cython automatisch beschleunigt, ohne dass der Code geändert wird (obwohl es natürlich schwierig sein wird, ihn vollständig zu beschleunigen). Ich persönlich bin glücklich, wenn es darum geht.
Ich konnte solche Informationen jedoch nicht in meiner Forschung finden. Wenn Sie Informationen zu Typhinweisen und zur Cython-Automatisierung haben, lassen Sie es mich bitte wissen.
Es ist ziemlich schnell, aber ich habe die Funktionen von Cython vorgestellt. Es gibt noch viele Funktionen von Cython, aber vorerst sollte es ausreichen, um mit Cython zu beschleunigen.
Wenn Sie sich einen Überblick über Cython verschaffen möchten, sind die folgenden Folien gut organisiert und empfohlen.
http://www.behnel.de/cython200910/talk.html
Recommended Posts