Introduction à Cython sans approfondir -2-

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.

Visite des débuts de la notation 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.

Déclaration de fonction

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

classe cdef

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

Liste des extensions de fichiers utilisées par Cython

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.

mode Python pur

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

Fichier .pxd agrémenté

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"

Coopération entre l'indice de type et Cython (observation optimiste)

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.

Résumé

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

Une introduction à Cython sans aller plus loin
Introduction à Cython sans approfondir -2-
Introduction à Word2Vec que même les chats peuvent comprendre
Une introduction à l'apprentissage automatique
Introduction au Deep Learning ~ Règles d'apprentissage ~
Une introduction à la programmation Python
Introduction à l'optimisation bayésienne
Apprentissage par renforcement profond 1 Introduction au renforcement de l'apprentissage
Introduction au Deep Learning ~ Rétropropagation ~
[Introduction à StyleGAN] Cet "homme qui ne rit pas" a souri sans le vouloir ♬
Introduction à Python que même les singes peuvent comprendre (partie 3)
Introduction à Python que même les singes peuvent comprendre (partie 1)
Introduction à Python que même les singes peuvent comprendre (partie 2)
Introduction à l'apprentissage en profondeur ~ Approximation des fonctions ~
Introduction au Deep Learning ~ Propagation vers l'avant ~
Introduction à l'apprentissage profond ~ Expérience CNN ~
Premiers pas avec Python pour les non-ingénieurs
[Tutoriel Python] Une introduction facile à Python
Une introduction aux Pandas pour apprendre tout en souffrant [Partie 1]
Introduction au Deep Learning ~ Pliage et mise en commun ~
Une introduction à OpenCV pour l'apprentissage automatique
Réseau neuronal récursif: une introduction à RNN
Une introduction à Python pour l'apprentissage automatique
Introduction au Deep Learning (1) --Chainer est expliqué d'une manière facile à comprendre pour les débutants-
Qu'est-ce qu'un algorithme? Introduction à l'algorithme de recherche] ~ Python ~
Une introduction à la programmation orientée objet pour les débutants par les débutants
Un amateur a essayé le Deep Learning avec Caffe (Introduction)
Introduction à la modélisation statistique pour l'analyse des données
Introduction à l'apprentissage profond ~ Fonction de localisation et de perte ~
Introduction à Python "Re" 1 Construction d'un environnement d'exécution
Une introduction à l'analyse vocale pour les applications musicales
Introduction à MQTT (Introduction)
Introduction à Scrapy (1)
Introduction à Scrapy (3)
Premiers pas avec Supervisor
Introduction à Tkinter 1: Introduction
Introduction à PyQt
Introduction à Scrapy (2)
[Linux] Introduction à Linux
Introduction à Scrapy (4)
Introduction à discord.py (2)
Introduction au traitement parallèle distribué Python par Ray
Note de lecture: Introduction à l'analyse de données avec Python
Comment créer un serveur HTTPS avec Go / Gin
Comment déployer une application Go sur une instance ECS
Introduction à l'apprentissage automatique à partir de Simple Perceptron