Warning: Undefined array key "DOKU_PREFS" in /home/clients/a4e6fc1ce1761b72982b805de0f418c4/web/python/mesrecettespython/inc/common.php on line 2082
exemple_cython_cpp [Les recettes Python de Tyrtamos]

Outils pour utilisateurs

Outils du site


exemple_cython_cpp

Warning: Undefined array key -1 in /home/clients/a4e6fc1ce1761b72982b805de0f418c4/web/python/mesrecettespython/inc/html.php on line 1458

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
exemple_cython_cpp [2013/10/17 12:42]
tyrtamos
exemple_cython_cpp [2013/10/18 18:20]
tyrtamos
Ligne 1: Ligne 1:
 ====== Exemple d'utilisation de Cython avec C++ ====== ====== Exemple d'utilisation de Cython avec C++ ======
- 
- 
-**//En cours de construction//** 
- 
  
 ===== Objectif ===== ===== Objectif =====
Ligne 15: Ligne 11:
 La fonction choisie pour l'exemple: le PGCD: plus grand commun diviseur de 2 nombres entiers. La fonction choisie pour l'exemple: le PGCD: plus grand commun diviseur de 2 nombres entiers.
  
-Suggestion: si vous voulez construire les 3 exemples ci-dessous et en faire des comparaisons de performances, il faut placer chacun d'eux dans un répertoire séparé, par exemple pgcd1, pgcd2 et pgcd3, et placer un fichier "__init__.py" vide à la racine de chacun d'eux. Cela vous permettra de tester les 3 exemples dans un programme test, dans lequel vous pourrez importer les 3 pgcd comme suit:+Suggestion: si vous voulez construire les 3 exemples ci-dessous et en faire des comparaisons de performances, il faut placer chacun d'eux dans un répertoire séparé, par exemple pgcd1, pgcd2 et pgcd3, et placer un fichier "%%__init__.py%%" vide (signature du "package" Python) à la racine de chacun d'eux
 + 
 +<code> 
 +essaicython (répertoire) 
 +    test.py (code de test des 3 exemples) 
 +     
 +    pgcd1 (répertoire) 
 +    __init__.py 
 +    ... (code de l'exemple 1) 
 + 
 +    pgcd2 (répertoire) 
 +    __init__.py 
 +    ... (code de l'exemple 2) 
 + 
 +    pgcd3 (répertoire) 
 +    __init__.py 
 +    ... (code de l'exemple 3) 
 +</code> 
 + 
 +Cela vous permettra de tester les 3 exemples dans un programme test, dans lequel vous pourrez importer les 3 pgcd comme suit:
  
 <code python> <code python>
Ligne 22: Ligne 37:
 from pgcd3.pgcd3 import pgcd3 from pgcd3.pgcd3 import pgcd3
 </code>  </code> 
 +
 +Attention sous Windows: choix du compilateur
 +
 +Python prendra le compilateur par défaut. Si vous avez Visual Studio de Microsoft (comme moi), c'est lui qui sera utilisé (ça fonctionne très bien!). Mais si vous voulez MinGW au lieu de Visual Studio, il y a 2 choses à faire:
 +
 +1- créer un fichier texte “setup.cfg” placé au même niveau que setup.py, et contenant:
 +
 +<code>
 +[build]
 +compiler = mingw32
 +</code>
 +
 +2- corriger le fichier C:\Python27\Lib\distutils\cygwinccompiler.py pour retirer toute mention de l'option "-mno-cygwin" si elle génère une erreur.
 +
 +Moyennant quoi, chez moi, ça marche avec les 2 compilateurs. 
  
 ===== Fonction codée en Python pur ===== ===== Fonction codée en Python pur =====
Ligne 41: Ligne 71:
  
 Il est difficile de faire plus simple! Il est difficile de faire plus simple!
- 
-L'utilisation de ce module nécessitera une simple importation:  
- 
-<code python> 
-from pgcd1 import pgcd1 
-</code> 
  
 ===== Fonction codée en Cython pour être compilée en C++ ===== ===== Fonction codée en Cython pour être compilée en C++ =====
Ligne 77: Ligne 101:
 A noter que j'utilise une syntaxe peu utilisée mais très pratique: toutes les définitions nécessaires à Cython pour compiler sont ajoutées sous forme de décorateurs. Cela permet de garder quasi intactes les fonctions en pur Python. A noter que j'utilise une syntaxe peu utilisée mais très pratique: toutes les définitions nécessaires à Cython pour compiler sont ajoutées sous forme de décorateurs. Cela permet de garder quasi intactes les fonctions en pur Python.
  
-Pour le tratement Cython, on fabrique le **setup.py** suivant:+Pour le traitement Cython, on fabrique le **setup.py** suivant:
  
 <code python> <code python>
Ligne 99: Ligne 123:
  
 Vous voyez que c'est dans le setup qu'on désigne le C++ comme choix du compilateur. Vous voyez que c'est dans le setup qu'on désigne le C++ comme choix du compilateur.
- 
- 
  
 Il ne reste plus qu'à exécuter le traitement par (à exécuter dans le répertoire du setup): Il ne reste plus qu'à exécuter le traitement par (à exécuter dans le répertoire du setup):
Ligne 106: Ligne 128:
 <code> <code>
 python setup.py build_ext --inplace python setup.py build_ext --inplace
-</code> 
- 
-L'utilisation de ce module nécessitera une simple importation:  
- 
-<code python> 
-from pgcd2 import pgcd2 
 </code> </code>
  
Ligne 122: Ligne 138:
 **bib.cpp**: **bib.cpp**:
  
-<code>+<code cpp>
 #include "bib.h" #include "bib.h"
  
Ligne 138: Ligne 154:
 Et l'en-tête **bib.h**: Et l'en-tête **bib.h**:
  
-<code>+<code cpp>
 int pgcd_(int a, int b); int pgcd_(int a, int b);
 </code> </code>
Ligne 198: Ligne 214:
 </code> </code>
  
-Et le module final pgcd3.pyd pourra être importé avec:+===== Utilisation et test de performance ===== 
 + 
 +Voilà le code qui permettra de tester les 3 exemples:
  
 <code python> <code python>
-from pgcd3 import pgcd3+#!/usr/bin/python 
 +# -*- coding: utf-8 -*- 
 +from __future__ import division 
 +# Python 2.7 
 + 
 +from pgcd1.pgcd1 import pgcd1 
 +from pgcd2.pgcd2 import pgcd2 
 +from pgcd3.pgcd3 import pgcd3 
 + 
 +from timeit import default_timer  
 +from random import randint 
 + 
 +n = 1000000 
 +a = randint(10,10000) 
 +b = randint(10,10000) 
 + 
 +t1 = default_timer() 
 +for c in xrange(0, n): 
 +    pgcd1(a, b) 
 +t1 = default_timer()-t1 
 +print t1 
 + 
 +t2 = default_timer() 
 +for c in xrange(0, n): 
 +    pgcd2(a, b) 
 +t2 = default_timer()-t2 
 +print t2 
 + 
 +t3 = default_timer() 
 +for c in xrange(0, n): 
 +    pgcd3(a, b) 
 +t3 = default_timer()-t3 
 +print t3 
 +print t2/t1, t3/t2
 </code> </code>
  
 +Exemple d'affichage:
 +
 +<code>
 +1.51095759895
 +0.330764389199
 +0.295863063216
 +0.218910437612 0.894482818819
 +</code>
 +
 +Constatations:
 +
 +  * le temps d'exécution de la fonction pgcd est divisé par 4 à 5 quand on prend le code Cython plutôt que le code en Python pur.
 +
 +  * Lorsque Cython appelle directement du code C++, on gagne encore 10% environ. Ce qui peut être intéressant si on dispose déjà du code C++, mais pas assez s'il faut l'écrire. 
 +
 +Conclusion: **//la solution "Cython" est vraiment intéressante!//**
 +
 +Attention cependant: lorsqu'on utilise dans Cython des variables de même type que C++, c'est très rapide, mais si on veut utiliser des variables Python qui n'existent pas en C++, ça se gâte un peu, parce qu'on oblige le C++ à faire de nombreux appels à l'API Python. A la limite, on peut obtenir un temps d'exécution plus long qu'en pur Python (ça m'est déjà arrivé)!
 +
 +Amusez-vous bien!
  
exemple_cython_cpp.txt · Dernière modification: 2013/10/18 18:20 de tyrtamos