Cet article est la suite de "Introduction à Cython sans Deep".
Commençons avec Cython pour ne pas aller trop loin cette fois. Le but de cet article n'est pas d'y entrer, mais de profiter de la délicieuse partie de Cython.
La notation Cython n'est pas trop difficile, j'ai un bon exemple de code dans le didacticiel Cython, alors empruntons-le.
Code avant optimisation
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)
Si vous optimisez le code ci-dessus avec Cython, il ressemblera à ceci.
Code d'optimisation Cython
%%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
Vous pouvez voir comment taper des variables, des arguments et des valeurs de retour en les regardant, il n'est donc pas nécessaire de les expliquer.
Si vous regardez attentivement les déclarations de fonction, la fonction myfunction est définie par cpdef
et la fonction _helper est définie par cdef
. La liste des déclarations de fonction est la suivante.
Déclaration | La description |
---|---|
def | Lent, peut être appelé depuis Python |
cdef | Rapide, non appelable depuis Python, uniquement disponible dans Cython |
cpdef | Un hybride de def et cdef, def lorsqu'il est appelé depuis Python, cdef lorsqu'il est appelé depuis Cython |
Si vous définissez cdef class A
dans la déclaration de classe, elle devient une classe cdef.
La classe cdef a une bonne efficacité mémoire et un accès rapide car elle est gérée par une structure, par rapport à la classe ordinaire qui gère les attributs par dict, mais elle est soumise aux restrictions suivantes.
La définition de membre doit être définie à l'avance comme suit.
cdef class A:
cdef public int x
cdef public int y
cdef double _scale
cdef readonly float read_only
...
Les références de Python ne sont possibles que si public est ajouté comme le membre _scale
.
De plus, si vous ajoutez l'attribut readonly
comme le membre read_only
, vous ne pouvez pas le changer depuis Python.
a = A()
a._scale #Erreur
a.read_only = 2.0 #Erreur
extension | La description |
---|---|
.pyx | Considérez-le comme un fichier d'implémentation ou le programme lui-même |
.pxd | Fichier de définition |
.pxi | Inclure le fichier |
Si vous connaissez ce qui précède, vous n'aurez aucun problème.
En fait, en tant que procédure pour accélérer un programme Python, il s'agit d'une procédure générale pour ajouter une définition de type au programme d'origine. Alors, proposons une approche différente, qui est le "mode Python pur".
Réécrivons l'exemple ci-dessus en mode Python pur.
pure_Exemple réécrit en mode Python
%%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
C'est un style que ʻimport cython` est ajouté au code Python et les informations de type sont ajoutées en le décorant. Vous pouvez maintenant exécuter le même fichier en Python et le compiler en Cython.
Étant donné que les informations de type sont définies en dehors de la fonction, la partie de code Python à l'intérieur de la fonction n'a pas du tout besoin d'être modifiée. La lisibilité de la partie de traitement reste la même, il est donc étonnamment confortable si vous vous habituez à la tempête des décorateurs.
Pour plus de détails sur le mode Python pur de Cython, consultez la documentation officielle. C'est un tutoriel concis, donc facile à lire car il n'y a presque pas de texte en anglais.
http://cython.readthedocs.io/en/latest/src/tutorial/pure.html
Vous pouvez accélérer le code dans la fonction car il est en mode Python pur, mais vous pouvez utiliser le fichier .pxd pour accélérer l'ensemble du fichier .py sans le changer.
Cette explication est un bref extrait du manuel officiel.
http://omake.accense.com/static/doc-ja/cython/src/tutorial/pure.html
S'il trouve un .pxd avec le même nom que le fichier> .py, Cython recherche les classes cdefed et les fonctions et méthodes cdef / cpdefed. Puis convertissez les classes / fonctions / méthodes correspondantes dans .py en types appropriés. Par conséquent, s'il y a un.pxd comme ci-dessous:
cdef class A:
cpdef foo(self, int i)
En même temps, si vous avez un fichier appelé a.py comme celui ci-dessous:
class A:
def foo(self, i):
print "Big" if i > 1000 else "Small"
Le code est interprété comme suit:
cdef class A:
cpdef foo(self, int i):
print "Big" if i > 1000 else "Small"
Si vous examinez attentivement le code en mode Python pur, vous pouvez voir [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% Similaire à 82% B0). J'utilise beaucoup les indices de type de PyCharm, donc j'ai trouvé le mode Python pur facile à utiliser.
Exemple d'indication de type PyCharm
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)
En outre, Python a un fichier stub (.pyi) qui contient uniquement des informations de type.
https://www.python.org/dev/peps/pep-0484/#stub-files
Le fichier stub est très similaire au "fichier agumenting.pxd" décrit à la fin.
À l'avenir, le code Python avec des indices de type ou des annotations de type sera automatiquement accéléré par Cython sans aucune modification du code (bien qu'il soit difficile de l'accélérer complètement, bien sûr). Je suis personnellement heureux quand il s'agit de cela.
Cependant, je n'ai pas trouvé de telles informations dans mes recherches, si vous avez des informations sur les indices de type et l'automatisation Cython, veuillez me le faire savoir.
C'est assez rapide, mais j'ai présenté les fonctionnalités de Cython. Il existe encore de nombreuses fonctionnalités de Cython, mais pour le moment, cela devrait suffire à accélérer avec Cython.
Si vous souhaitez avoir un aperçu de Cython, les diapositives ci-dessous sont bien organisées et recommandées.
http://www.behnel.de/cython200910/talk.html
Recommended Posts