Ce site réponse de @Dunes affirme qu'en raison du pipeline, il n'y a (presque) aucune différence entre la multiplication et la division en virgule flottante. Cependant, d'après mon expérience avec d'autres langages, je m'attendrais à ce que la division soit plus lente.
Mon petit test se présente comme suit :
A=np.random.rand(size)
command(A)
Pour les différentes commandes et size=1e8
J'obtiens les temps suivants sur ma machine :
Command: Time[in sec]:
A/=0.5 2.88435101509
A/=0.51 5.22591209412
A*=2.0 1.1831600666
A*2.0 3.44263911247 //not in-place, more cache misses?
A+=A 1.2827270031
La partie la plus intéressante : la division par 0.5
est presque deux fois plus rapide que la division par 0.51
. On pourrait supposer que cela est dû à une optimisation intelligente, par exemple en remplaçant la division par A+A
. Cependant, les horaires de A*2
y A+A
sont trop éloignés pour soutenir cette affirmation.
En général, la division par des flottants avec des valeurs (1/2)^n
est plus rapide :
Size: 1e8
Command: Time[in sec]:
A/=0.5 2.85750007629
A/=0.25 2.91607499123
A/=0.125 2.89376401901
A/=2.0 2.84901714325
A/=4.0 2.84493684769
A/=3.0 5.00480890274
A/=0.75 5.0354950428
A/=0.51 5.05687212944
C'est encore plus intéressant, si on regarde size=1e4
:
Command: 1e4*Time[in sec]:
A/=0.5 3.37723994255
A/=0.51 3.42854404449
A*=2.0 1.1587908268
A*2.0 1.19793796539
A+=A 1.11329007149
Maintenant, il n'y a aucune différence entre la division par .5
et par .51
!
Je l'ai essayé pour différentes versions de numpy et différentes machines. Sur certaines machines (par exemple Intel Xeon E5-2620) on peut voir cet effet, mais pas sur d'autres machines - et cela ne dépend pas de la version de numpy.
Avec le script de @Ralph Versteegen (voir son excellente réponse !) j'obtiens les résultats suivants :
- timings avec i5-2620 (Haswell, 2x6 cœurs, mais une très vieille version de numpy qui n'utilise pas SIMD) :
- timings avec i7-5500U (Broadwell, 2 cœurs, numpy 1.11.2) :
La question est la suivante : Quelle est la raison du coût plus élevé de la division en 0.51
par rapport à la division par 0.5
pour certains processeurs, si la taille des tableaux est importante (>10^6).
La réponse de @nneonneo indique que pour certains processeurs intel, il y a une optimisation lors de la division par des puissances de deux, mais cela n'explique pas pourquoi nous n'en voyons l'avantage que pour les grands tableaux.
La question initiale était "Comment ces différents comportements (division par 0.5
vs. la division par 0.51
) s'explique ?"
Ici aussi, mon test original script, qui a produit les timings :
import numpy as np
import timeit
def timeit_command( command, rep):
print "\t"+command+"\t\t", min(timeit.repeat("for i in xrange(%d):"
%rep+command, "from __main__ import A", number=7))
sizes=[1e8, 1e4]
reps=[1, 1e4]
commands=["A/=0.5", "A/=0.51", "A*=2.2", "A*=2.0", "A*2.2", "A*2.0",
"A+=A", "A+A"]
for size, rep in zip(sizes, reps):
A=np.random.rand(size)
print "Size:",size
for command in commands:
timeit_command(command, rep)