Voir la version complète : Optimisation en Python
César Vonc
17/09/2012, 15h24
Bonjour,
Ce sujet a pour but de regrouper les petites astuces permettant d'augmenter la vitesse d'exécution d'un code Python.
Exemple de chronomètre :
import time
import c4d
def chrono():
t = time.time()
for i in xrange(10000000) :
pass
print time.time() - t
if __name__=='__main__':
chrono()
--
Vérifier un booléen :
if a is True :██████████ 0,70 s
if a :
█████ 0,35 s - Gain de 50 %
--
Boucle :
for i in range(10000000) :██████████ 0,84 s
for i in xrange(10000000) :███ 0,24 s - Gain de 71 %
César Vonc
17/09/2012, 15h42
Je découvre des choses intéressantes, si quelqu'un a une explication, elle est la bienvenue :
Créer un vecteur :
v = c4d.Vector(0, 0, 0)██████████ 4,25 s
v = c4d.Vector(0.0, 0.0, 0.0)█████████ 3,86 s - Gain de 10 %
v = c4d.Vector()██████ 2,60 s - Gain de 39 %
Il en va de même pour créer un vecteur quelconque ayant les trois mêmes valeurs, Vector(1.0) sera plus rapide que Vector(1.0, 1.0, 1.0) et Vector(1, 1, 1).
Ma théorie :
Dans le premier cas, j'imagine que Python doit convertir les entiers en flottants, ce qui rend le second cas plus rapide étant donné qu'on entre flottants directement, et le dernier cas n'a probablement pas à vérifier les valeurs entrées, d'où le gain.
Salut,
Super sujet César. :thumbup1:
Voilà un petit bout de code pour comparer le temps d'execution de 2 instructions :
import timeit
import c4d
LOOP_COUNT = 10000000
def compare(stmt1, stmt2):
t1 = timeit.Timer(stmt1, "import c4d").timeit(number=LOOP_COUNT)
t2 = timeit.Timer(stmt2, "import c4d").timeit(number=LOOP_COUNT)
print "Statement 1 : %.3f s" % t1
print "Statement 2 : %.3f s" % t2
faster = 1 if t1 < t2 else 2
if faster == 2:
t1, t2 = t2, t1
diff = t2 - t1
percent = 100.0 - t1 / t2 * 100.0
print "-> Statement %d is %.3f s (%.1f %%) faster" % (faster, diff, percent)
test1 = """
a = 42
if a & 1:
pass
"""
test2 = """
a = 42
if a % 2:
pass
"""
def main():
compare(test1, test2)
Pour le c4d.Vector, je pense que tu as raison, la conversion implicite prend du temps. Cela se vérifie en comparant :
a = 1.0
a += 1.0
plus rapide (~ 10 %) que
a = 1.0
a += 1
Aussi
a = b = c = x
plus rapide (~ 14 %) que
a, b, c = x, y, z
et de ce fait "c4d.Vector(1)" sera quand même plus rapide que "c4d.Vector(1.0, 1.0, 1.0)" mais moins que "c4d.Vector(1.0)"
Attention certains exemples sont destinés à être utilisés uniquement dans le cas d'un problème de rapidité avéré.
Tester la nullité d'un entier :
if a == 0 :██████████ 6,04 s
if not a :█████████ 5,38 s - Gain de 11 %
--
Tester la positivité d'un index inférieur :
if i - 1 > 0:██████████ 0,80 s
if i > 1:████████ 0,60 s - Gain de 25 %
--
Insérer dans un tableau :
tab = []
for i in xrange(5):
tab.append(i) ██████████ 1,44 s
tab = []
append = tab.append
for i in xrange(5):
append(i)█████████ 1,22 s - Gain de 15 %
--
Opérations sur les vecteurs :
v = c4d.Vector(10, 20, 30)
w = c4d.Vector(1, 2, 3)
x = c4d.Vector(v.x * w.x, v.y * w.y, v.z * w.z)
y = c4d.Vector(v.x + w.x, v.y + w.y, v.z + w.z)██████████ 2,75 s
v = c4d.Vector(10, 20, 30)
w = c4d.Vector(1, 2, 3)
x = v ^ w
y = v + w████ 0,99 s - Gain de 64 %
--
Tester si le tableau contient au moins 1 élément :
a = []
if len(a) == 0:██████████ 1,52 s
a = []
if not a:█████ 0,76 s - Gain de 50 %
César Vonc
26/09/2012, 16h37
Excellent, Yann !
Dis donc, je connaissais pas cette formulation :
tab = []
append = tab.append
for i in xrange(5):
append(i) C'est plutôt curieux, append a quel type ?
>>> tab = []
>>> append = tab.append
>>> type(append)
<type 'builtin_function_or_method'>
C'est le même principe que les pointeurs sur fonctions en C++.
Deux liens en anglais avec pleins de conseils :
http://wiki.python.org/moin/PythonSpeed/PerformanceTips
http://stackoverflow.com/questions/7165465/optimizing-python-code
César Vonc
29/09/2012, 17h27
Merci pour les liens.
Division de flottants :
a = 5.0 / 2██████████ 1,00 s
a = 5.0 / 2.0████████ 0,80 s - Gain de 20 %
a = 5.0 * 0.5████ 0,36 s - Gain de 64 %
Préférer la multiplication plutôt que la division tant que possible.
Remplacer 1/3 par 0,333 est préférable si la précision n'est pas de mise.
Note : 5 / 2 renverra un nombre entier (2).
César Vonc
23/01/2014, 13h00
Édit : finalement tout ça était faux, il faut mieux rester avec des vecteurs tout le temps car la conversion de vecteurs en tuples est beaucoup trop longue.
Powered by vBulletin® Version 4.2.1 Copyright © 2024 vBulletin Solutions, Inc. Tous droits réservés