237 votes

Qu'est-ce qui est le plus rapide en Python : x**.5 ou math.sqrt(x) ?

Je me pose cette question depuis un certain temps. Comme le dit le titre, qu'est-ce qui est le plus rapide, la fonction proprement dite ou la simple élévation à la moitié de la puissance ?

UPDATE

Il ne s'agit pas d'une optimisation prématurée. Il s'agit simplement de savoir comment le code sous-jacent fonctionne réellement. Quelle est la théorie sur le fonctionnement du code Python ?

J'ai envoyé un courriel à Guido van Rossum parce que je voulais vraiment connaître les différences entre ces méthodes.

Mon email :

Il existe au moins 3 façons de faire une racine carrée en Python : math.sqrt, l'opérateur '**' et pow(x,.5). l'opérateur '**' et pow(x,.5). Je suis juste curieux de savoir quelles sont les différences dans l'implémentation de chacune d'entre elles. En termes d'efficacité, quelle est la meilleure est la meilleure ?

Sa réponse :

pow et ** sont équivalents ; math.sqrt ne fonctionne pas pour les nombres complexes, et renvoie à la fonction C sqrt(). Quant à savoir laquelle est rapide, je n'en ai aucune idée...

114 votes

C'est génial que le Guido réponde aux emails.

3 votes

Evan, j'ai été surpris d'avoir une réponse

13 votes

Je ne pense pas que ce soit une mauvaise question. Par exemple, x * x est 10 fois plus rapide que x ** 2. La lisibilité est un tossup dans cette situation, alors pourquoi ne pas faire la méthode rapide ?

116voto

Claudiu Points 58398

math.sqrt(x) est nettement plus rapide que `x0.5` .**

import math
N = 1000000

%%timeit
for i in range(N):
    z=i**.5

10 boucles, best of 3 : 156 ms par boucle

%%timeit
for i in range(N):
    z=math.sqrt(i)

10 boucles, meilleur de 3 : 91.1 ms par boucle

Utilisation de Python 3.6.9 ( ordinateur portable ).

0 votes

Je l'ai maintenant exécuté 3 fois sur codepad.org et les trois fois a() était beaucoup plus rapide que b().

0 votes

Avec ma machine en local, il faut ~0,12 secondes pour que a et ~0,16 seconde pour b . Intéressant.

0 votes

Essayez de déplacer la fonction sqrt dans la portée locale, de sorte qu'elle n'ait pas besoin de chercher maths dans le dictionnaire global puis sqrt dans ce dictionnaire.

22voto

J.F. Sebastian Points 102961
  • première règle de l'optimisation : ne le faites pas
  • deuxième règle : ne le faites pas pourtant

Voici quelques timings (Python 2.5.2, Windows) :

$ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
1000000 loops, best of 3: 0.445 usec per loop

$ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
1000000 loops, best of 3: 0.574 usec per loop

$ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
1000000 loops, best of 3: 0.727 usec per loop

Ce test montre que x**.5 est légèrement plus rapide que sqrt(x) .

Pour Python 3.0, le résultat est inverse :

$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
1000000 loops, best of 3: 0.803 usec per loop

$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
1000000 loops, best of 3: 0.695 usec per loop

$ \Python30\python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
1000000 loops, best of 3: 0.761 usec per loop

math.sqrt(x) est toujours plus rapide que x**.5 sur une autre machine (Ubuntu, Python 2.6 et 3.1) :

$ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
10000000 loops, best of 3: 0.173 usec per loop
$ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
10000000 loops, best of 3: 0.115 usec per loop
$ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
10000000 loops, best of 3: 0.158 usec per loop
$ python3.1 -mtimeit -s"from math import sqrt; x = 123" "x**.5"
10000000 loops, best of 3: 0.194 usec per loop
$ python3.1 -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
10000000 loops, best of 3: 0.123 usec per loop
$ python3.1 -mtimeit -s"import math; x = 123" "math.sqrt(x)"
10000000 loops, best of 3: 0.157 usec per loop

2 votes

Pourquoi ai-je tant de mal à suivre cette règle ?

0 votes

0 votes

@JDB Je ne vois pas comment cela s'applique à ma réponse qui est principalement sur "mesurer d'abord" : optimiser seulement si les mesures montrent que l'optimisation est nécessaire dans votre cas.

17voto

JimB Points 9246

Dans ces micro-benchmarks, math.sqrt sera plus lent, en raison du léger temps nécessaire à la recherche de l'adresse de l'utilisateur. sqrt dans l'espace de nom mathématique. Vous pouvez l'améliorer légèrement avec

 from math import sqrt

Même dans ce cas, l'exécution de quelques variations à travers timeit, montre un léger avantage (4-5%) en termes de performances pour x**.5

Il est intéressant de noter que faire

 import math
 sqrt = math.sqrt

l'a accéléré encore plus, avec une différence de vitesse de moins de 1%, avec une signification statistique très faible.


Je vais répéter Kibbee, et dire que c'est probablement une optimisation prématurée.

1 votes

La raison qui définit sqrt dans l'espace de nom local du programme accélère davantage est probablement dû à l'ordre de résolution des méthodes : le compilateur vérifie d'abord si la fonction a été définie dans votre code, puis dans les importations éventuelles, donc si elle a été définie localement, cela prend moins de temps par recherche.

9voto

Kibbee Points 36474

Combien de racines carrées exécutez-vous réellement ? Essayez-vous d'écrire un moteur graphique 3D en Python ? Si ce n'est pas le cas, alors pourquoi choisir un code cryptique plutôt qu'un code facile à lire ? La différence de temps serait inférieure à ce que l'on pourrait remarquer dans n'importe quelle application que je pourrais envisager. Je ne veux vraiment pas rabaisser votre question, mais il semble que vous alliez un peu trop loin dans l'optimisation prématurée.

21 votes

Je n'ai pas vraiment l'impression de faire une optimisation prématurée. Il s'agit plutôt de décider, parmi deux méthodes différentes, laquelle sera, en moyenne, plus rapide.

2 votes

Kibbee : c'est une question tout à fait valable, mais je partage votre désarroi face au nombre de questions sur Stack Overflow qui laissent entendre que le demandeur effectue toutes sortes d'optimisations prématurées. C'est certainement un pourcentage important des questions posées pour chaque langage.

0 votes

Mais quelle importance cela a-t-il vraiment ? Cela n'aura absolument aucun impact sur un quelconque programme.

3voto

strager Points 41713

Très probablement math.sqrt(x), parce qu'il est optimisé pour la racine carrée.

Les repères vous fourniront la réponse que vous recherchez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X