Pourquoi le code Python s'exécute-t-il plus vite dans une fonction?
def main():
for i in xrange(10**8):
pass
main()
Ce bout de code en Python exécute dans (Remarque: La synchronisation se fait avec la fonction de temps en BASH sous Linux.)
real 0m1.841s
user 0m1.828s
sys 0m0.012s
Toutefois, si la boucle n'est pas placé à l'intérieur d'une fonction,
for i in xrange(10**8):
pass
puis il exécute pour un temps beaucoup plus long:
real 0m4.543s
user 0m4.524s
sys 0m0.012s
Pourquoi est-ce?
source d'informationauteur thedoctar
Vous devez vous connecter pour publier un commentaire.
Vous pourriez vous demander pourquoi il est plus rapide pour stocker les variables locales que globales. C'est un Disponible détail d'implémentation.
Rappelez-vous que Disponible est compilé en bytecode, qui l'interprète exécute. Lorsqu'une fonction est compilé, les variables locales sont stockées dans un tableau de taille fixe (pas un
dict
) et les noms de variables sont affectées à l'index. Cela est possible parce que vous ne pouvez pas ajouter dynamiquement des variables locales à une fonction. Puis récupérer une variable locale est littéralement un pointeur de recherche dans la liste et le refcount augmentation de laPyObject
qui est trivial.Cela contraste global de recherche (
LOAD_GLOBAL
), qui est un vraidict
de recherche impliquant un hachage et ainsi de suite. D'ailleurs, c'est pourquoi vous avez besoin de spécifierglobal i
si vous voulez qu'il soit global: si jamais vous affecter à une variable à l'intérieur d'un champ, le compilateur émetSTORE_FAST
s pour son accès, sauf si vous lui dites de ne pas.Par le moyen global des recherches sont encore assez optimisé. Attribut recherches
foo.bar
sont les vraiment lent!Voici le petit illustration sur la variable locale de l'efficacité.
L'intérieur d'une fonction, le bytecode est
Au plus haut niveau, le bytecode est
La différence est que
STORE_FAST
est plus rapide (!) queSTORE_NAME
. C'est parce que dans une fonction,i
est local, mais au niveau supérieur, il est mondial.Pour examiner bytecode, utilisez le
dis
module. J'ai pu démonter la fonction directement, mais de démonter le toplevel code que j'ai eu à utiliser lacompiler
builtin.À part local/global variable magasin fois, opcode prédiction rend la fonction plus rapide.
Que les autres réponses expliquer, la fonction utilise la
STORE_FAST
opcode dans la boucle. Voici le pseudo-code pour la fonction de boucle:Normalement, lorsqu'un programme est exécuté, Python exécute chaque opcode l'un après l'autre, en gardant la trace de la pile et de préformage d'autres contrôles sur le frame de pile après chaque opcode est exécutée. Opcode prédiction signifie que, dans certains cas, le langage Python est capable de sauter directement à la prochaine opcode, évitant ainsi certains de ces frais.
Dans ce cas, à chaque fois que Python voit
FOR_ITER
(en haut de la boucle), il "prédit" queSTORE_FAST
est la prochaine opcode il a à exécuter. Python puis jettant un oeil à la prochaine opcode et, si la prédiction était correcte, il saute directement àSTORE_FAST
. Cela a pour effet de comprimer les deux opérateurs dans un seul opcode.D'autre part, la
STORE_NAME
opcode est utilisée dans la boucle au niveau mondial. Python n' *pas* faire des prédictions similaires lorsqu'il voit cet opcode. Au lieu de cela, il doit revenir à la partie supérieure de l'évaluation de la boucle qui a des répercussions évidentes sur la vitesse à laquelle la boucle est exécutée.Pour donner plus de détails techniques sur cette optimisation, voici une citation de la
ceval.c
fichier (le "moteur" de Python de la machine virtuelle):Nous pouvons le voir dans le code source de la
FOR_ITER
opcode exactement où la prédiction pourSTORE_FAST
est fait:La
PREDICT
fonction s'étend àif (*next_instr == op) goto PRED_##op
c'est à dire juste sauter au début de la prédiction de l'opcode. Dans ce cas, on saute ici:La variable locale est maintenant réglée et la prochaine opcode est en place pour l'exécution. Python se poursuit à travers le itératif jusqu'à ce qu'il atteigne la fin, en faisant le succès de la prédiction à chaque fois.
La Python page wiki a plus d'informations sur comment Disponible de la machine virtuelle fonctionne.