Différences

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
Dernière révision Les deux révisions suivantes
articles:python_benchmark [2010/06/16 18:22]
nico
articles:python_benchmark [2010/06/17 21:15]
nico
Ligne 1: Ligne 1:
 +======Python benchmark : accélérer ses calculs======
  
 +Tous les résultats sont indiqués en secondes.
 +
 +La fonction something() consiste généralement au choix d'un nombre flottant aléatoire :
 +
 +<code python>
 +from random import uniform
 +def something():​
 +    return uniform(-100000,​100000)
 +</​code> ​
 +
 +Bien que ne semblant avoir indépendemment que peu d'​effets,​ l'​application de l'​ensemble de ces astuces dans un programme peut avoir un effet drastique sur son temps d'​exécution.
 +
 +=====Boucles======
 +
 +====While et for====
 +
 +Boucle while :
 +<code python>
 +i = 0
 +while i < x:
 +    something()
 +    i += 1 
 +</​code>​
 +
 +Boucle for :
 +<code python>
 +for i in range(x):
 +    something()
 +</​code>​
 +
 +Boucle for préparée :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    something()
 +</​code>​
 +
 +===Bench===
 +
 +Moyenne de 10 essais sur des boucles à 1.000.000 de tours :
 +
 +  - Boucle while : 0.6407999277
 +  - Boucle for :  0.6034000397
 +  - Boucle for préparée :  0,​5895000458
 +
 +<​barchart>​0|50x20|100|While:​100,​For:​94,​For2:​76</​barchart>​
 +
 +Moyenne de 1.000.000 d'​essais sur des boucles à 10 tours :
 +
 +  - Boucle while : 0.000006115
 +  - Boucle for :  0.000006264
 +  - Boucle for préparée :  0,000005651
 +
 +<​barchart>​0|50x20|100|While:​91,​For:​100,​For2:​70</​barchart>​
 +
 +===Conclusion===
 +
 +La boucle for devant parcourir une liste d'​éléments,​ l'​initialisation de ladite liste lui prend du temps, problème que ne rencontre pas la boucle while. La boucle while est donc plus rapide lorsqu'​il faut faire beaucoup de fois peu de tours.
 +
 +Une fois lancée la boucle for se montre par contre bien plus véloce que sa voisine, qui s'​encombre à chaque tour de boucle d'une opération sur le compteur. La boucle for est donc plus rapide lorsqu'​il faut faire peu de fois beaucoup de tours.
 +
 +La boule for "​préparée",​ en n'​apellant plus la fonction range() à chaque tour, se montre la plus véloce dans toutes les situations.
 +
 +====Appel de fonction====
 +
 +Appel dans une boucle :
 +<code python>
 +def doit():
 +    something()
 +    ​
 +rng = range(x)
 +for i in rng:
 +    doit()
 +</​code>​
 +
 +Boucle dans la fonction :
 +<code python>
 +def doit(x):
 +    rng = range(x)
 +    for i in rng:
 +        something() ​
 +        ​
 +doit(x)
 +</​code>​
 +
 +===Bench===
 +
 +1.000.000 de tours :
 +
 +  - Appel dans une boucle : 1.341
 +  - Boucle dans la fonction : 1.164
 +
 +<​barchart>​0|50x20|100|Dans:​100,​Hors:​70</​barchart>​
 +
 +===Conclusion===
 +
 +L'​appel à une fonction prends du temps, il est donc bien plus rapide de mettre la boucle à l'​intérieur de la fonction.
 +
 +=====Imports=====
 +
 +====From et import====
 +
 +From :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    from math import *
 +    something()
 +</​code>​
 +
 +<note important>​Cette syntaxe (//import *//) n'est correcte qu'au premier niveau du programme. J'ai ici passé outre les alertes afin d'en calculer la vitesse.</​note>​
 +
 +From limité :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    from math import pi
 +    something()
 +</​code>​
 +
 +Import :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    import math
 +    something()
 +</​code>​
 +
 +===Bench===
 +
 +1.000.000 de tours :
 +
 +  - From : 12.56
 +  - From limité : 2.99
 +  - Import : 0.99
 +
 +<​barchart>​0|50x20|13|From:​12.56,​From2:​2.99,​Import:​0.99</​barchart>​
 +
 +===Conclusion===
 +
 +En cas de besoin ou de volonté d'​utiliser la syntaxe //from//, l'​import d'​éléments précis dans le module s'​avère cinq à six fois plus véloce que l'​import complet dudit module.
 +
 +L'​utilisation de la syntaxe //import// seule reste quand à elle de 12 à 13 fois plus efficiente.
 +
 +====Réimporter====
 +
 +Import multiple :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    import math
 +    something()
 +</​code>​
 +
 +Import unique :
 +<code python>
 +import math
 +rng = range(x)
 +for i in rng:
 +    something()
 +</​code>​
 +
 +===Bench===
 +
 +1.000.000 de tours :
 +
 +  - Import multiple : 9.95
 +  - Import unique : 0.79
 +
 +<​barchart>​0|50x20|10|Multiple:​9.95,​Unique:​0.79</​barchart>​
 +
 +===Conclusion===
 +
 +Un import peut-être très long (cela dépend de la taille du module), il faut donc toujours éviter d'​importer plusieurs fois la même chose, en faisant par exemple :
 +
 +<code python>
 +math = None
 +rng = range(x)
 +for i in rng:
 +    if math is None:
 +        import math  ​
 +    something()
 +</​code>​
 +
 +
 +=====Opérateurs=====
 +
 +====Division et multiplication====
 +
 +Division :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    123456.789 / 4
 +</​code>​
 +
 +Multiplication :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    123456.789 * 0.25
 +</​code>​
 +
 +Le résultat de ces calculs est le même.
 +
 +===Bench===
 +
 +Calcul effectué 1.000.000 de fois :
 +
 +  - Division : 0.121
 +  - Multiplication : 0.047
 +
 +<​barchart>​0|50x20|12.1|Division:​12.1,​Multiplication:​4.7</​barchart>​
 +
 +===Conclusion===
 +
 +La multiplication est de deux à quatre fois plus rapide que la division.
 +
 +====Incrémentation et addition====
 +
 +Addition :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    i = i + 1
 +</​code>​
 +
 +Incrémentation :
 +<code python>
 +rng = range(x)
 +for i in rng:
 +    i += 1
 +</​code>​
 +
 +===Bench===
 +
 +Calcul effectué 1.000.000 de fois :
 +
 +  - Addition : 0.140
 +  - Incrémentation : 0.117
 +
 +<​barchart>​0|50x20|14|Addition:​14,​Incrémentation:​11.7</​barchart>​
 +
 +===Conclusion===
 +
 +L'​incrémentation est légèrement plus rapide que l'​addition.
 +
 +=====Classes====
 +
 +====Accès aux méthodes====
 +
 +Point dans la boucle :
 +<code python>
 +arr = []
 +rng = range(x)
 +for i in rng:
 +    arr.append(something())
 +</​code>​
 +
 +Point hors de la boucle :
 +<code python>
 +arr = []
 +append = arr.append
 +rng = range(x)
 +for i in rng:
 +    append(something())
 +</​code>​
 +
 +===Bench===
 +
 +Calcul effectué 1.000.000 de fois :
 +
 +  - Point dans la boucle : 1.307
 +  - Point hors de la boucle : 1.157
 +
 +<​barchart>​0|50x20|1.3|Dans:​1.3,​Hors:​1.1</​barchart>​
 +
 +===Conclusion===
 +
 +La référence à une méthode de classe (syntaxe du point), au lieu d'​être recalculée à chaque tour de boucle, peut être une fois pour toutes stockée dans une variable, accélérant notablement les calculs.
 +
 +=====WIP=====
 +En cours d'​écriture.
 +
 +A venir : benchmark code, parcourt et tri de tableaux/​listes et dictionnaires,​ concaténation et vitesse des opérateurs mathématiques et de comparaison.
 +
 +~~DISCUSSION~~