web-dev-qa-db-fra.com

gamme intégrée ou numpy.arange: quel est le plus efficace?

Lors de l'itération sur un grand tableau avec une expression de plage, dois-je utiliser la fonction de plage intégrée de Python, ou arange de numpy pour obtenir les meilleures performances?

Mon raisonnement jusqu'à présent:

arange a probablement recours à une implémentation native et pourrait donc être plus rapide. D'un autre côté, arange renvoie un tableau complet, qui occupe de la mémoire, il peut donc y avoir une surcharge. Python 3 est un générateur, qui ne contient pas toutes les valeurs en mémoire.

50
clstaudt

Pour les grands tableaux, numpy devrait être la solution la plus rapide.

Dans numpy, vous devez utiliser des combinaisons de calculs vectorisés, funcs et indexation pour résoudre vos problèmes car il s'exécute à la vitesse C. La boucle sur des tableaux numpy est inefficace par rapport à cela.

(La pire chose que vous pourriez faire serait de parcourir le tableau avec un index créé avec range ou np.arange comme le suggère la première phrase de votre question, mais je ne sais pas si vous pensez vraiment cela.)

import numpy as np
import sys

sys.version
# out: '2.7.3rc2 (default, Mar 22 2012, 04:35:15) \n[GCC 4.6.3]'
np.version.version
# out: '1.6.2'

size = int(1E6)

%timeit for x in range(size): x ** 2
# out: 10 loops, best of 3: 136 ms per loop

%timeit for x in xrange(size): x ** 2
# out: 10 loops, best of 3: 88.9 ms per loop

# avoid this
%timeit for x in np.arange(size): x ** 2
#out: 1 loops, best of 3: 1.16 s per loop

# use this
%timeit np.arange(size) ** 2
#out: 100 loops, best of 3: 19.5 ms per loop

Donc, dans ce cas, numpy est 4 fois plus rapide que l'utilisation de xrange si vous le faites correctement. Selon votre problème, numpy peut être beaucoup plus rapide qu'une accélération de 4 ou 5 fois.

Les réponses à cette question expliquent certains avantages supplémentaires de l'utilisation des tableaux numpy au lieu des listes python pour les grands ensembles de données).

58
bmu

Tout d'abord, comme écrit par @bmu, , vous devez utiliser des combinaisons de calculs vectorisés, d'ufuncs et d'indexation . Il existe en effet certains cas où un bouclage explicite est requis, mais ceux-ci sont vraiment rares.

Si une boucle explicite est nécessaire, avec python 2.6 et 2.7, vous devez utiliser xrange (voir ci-dessous). vous dites, dans Python 3, la plage est identique à xrange (retourne un générateur). Donc, la plage est aussi bonne pour vous.

Maintenant, vous devriez l'essayer vous-même (en utilisant timeit: - ici la "fonction magique" ipython):

%timeit for i in range(1000000): pass
[out] 10 loops, best of 3: 63.6 ms per loop

%timeit for i in np.arange(1000000): pass
[out] 10 loops, best of 3: 158 ms per loop

%timeit for i in xrange(1000000): pass
[out] 10 loops, best of 3: 23.4 ms per loop

Encore une fois, comme mentionné ci-dessus, la plupart du temps, il est possible d'utiliser une formule vecteur/tableau numpy (ou ufunc etc ...) qui exécute une vitesse c: beaucoup plus rapide. C'est ce que nous pourrions appeler la "programmation vectorielle". Il rend le programme plus facile à implémenter que C (et plus lisible) mais presque aussi rapide à la fin.

10
Juh_