Python et C++, stratégies

On n’utilise le C/C++ que dans le but d’accélérer un programme Python. Il existe plusieurs façons de mélanger les deux langages.

CPython

L’interpréteur Python a toujours été écrit en C. CPython est l’implémentation en C des modules standards autrefois écrits en Python. CPython est aussi une machine virtuelle comme l’est Java. Les programmes Python sont compilés sous forme bytecode (qu’il est possible d’analyser avec le module dis) puis exécutés.

C++ et Python séparés avec ctypes

Le module ctypes permet d’utiliser une librairie compilée séparément (DLL sous Windows). Le programme Python déclare les fonctions qu’il souhaite utiliser. Les interfaces sont souvent écrites en C. C’est l’option choisie par la librairie XGBoost.

La librairie C++ est compilée et expose des fonctions via une API C : c_api.h. Une fois la compilation terminée, il faut recopier la librairie compilée (instructions). Cette librairie est incluse dans le fichier setup.py lorsque celui-ci est buildé. Dans le code du package, la librairie est chargé via la fonction _load_lib. Les méthodes de la DLL sont appelées comme elles le seraient dans un programme python. Exemple avec la fonction XGDMatrixCreateFromFile.

Il est préférable de connaître le C/C++ pour comprendre pourquoi les types Python et C sont différentes ou encore ce que veut ctypes.byref.

C++ avec Cython

C’est l’option choisie par beaucoup de modules tels que scikit-learn. C’est aussi la moins verbeuse et la plus accessible surtout qu’il possible de s’interface facilement avec numpy.

Les fichiers d’extension pyd déclarent les fonctions qui seront implémentées en Cythno. Ils sont optionnels. Les fichiers d’extensions pyx implémentent des fonctions en Cython. Exemple : _utils.pyd et _utils.pyx. Ces fichiers sont toujours accompagnés d’instructions de compilation : tree/setup.py et setup.py.

Cython permet aussi d’écrire du code en allégeant la contrainte sur le GIL ou Global Interpreter Lock. Celui-ci impose l’exécution du langage sur un seul thread. Il faut savoir ce qu’on fait quand on relâche cette contrainte mais c’est le seul moyen d’écrire un programme vraiment parallèle.

Le langage Python effectue constamment plein de vérifications comme le fait qu’un indice soit en dehors d’une liste. Cython permet d’écrire un code plus rapide mais moins sûr en esquivant ces contraintes :

Le plus simple pour commencer à se familiariser est d’utiliser la commande magique %%cython qui effectue les opérations de compilation pour le programmeur.

Modules Python écrits en C

Il faut lire le tutoriel Extending Python with C or C++ <https://docs.python.org/3/extending/extending.html>_. C’est la solution qui produit le code le plus efficace mais il faut constamment convertir des données depuis Python vers C et réciproquement. Il faut aussi gérer soi-même le `comptage des références afin que le garbage collector garde la trace des objets créés et détruits.

Cette option est devenue moins intéressente avec les récents développement de Python. Il faut citer deux outils qui permettent de faciliter l’habillage d’une librairie C en Python :

Compiler le langage Python

Le langage Python n’est pas compilable mais certains outils tentent de convertir un code existant en C/C++ pour le compiler ensuite. Un des problèmes rencontrés est l”inférence de type : la compilateur requiert la connaissance du type d’une variable et celui n’est connu qu’à l’exécution. Quelques outils :

Tous repose sur un mécanisme appelé JIT ou compilation à la volée.

Un exemple

Le module cpyquickhelper implémente quelques façons de mettre du C dans un module Python et contient toutes les instructions pour en faire un module compilé et prêt à l’emploi.