2012-05-22 7 views
32

Wenn ich über ein großes Array mit einem Bereichsausdruck iteriere, sollte ich die integrierte Bereichsfunktion von Python oder arange von numpy verwenden, um die beste Leistung zu erhalten? so weitBuilt-in-Bereich oder numpy.arange: was ist effizienter?

Meine Argumentation:

arange wahrscheinlich greift auf eine native Implementierung und könnte schneller deshalb sein. Auf der anderen Seite gibt arange ein vollständiges Array zurück, das Speicher belegt, so dass möglicherweise ein Overhead entsteht. Der Bereichsausdruck von Python 3 ist ein Generator, der nicht alle Werte im Speicher enthält.

Antwort

39

Für große Arrays sollte numpy die schnellere Lösung sein.

In numpy sollten Sie Kombinationen von vektorisierten Berechnungen verwenden, ufuncs und indexing, um Ihre Probleme zu lösen, wie es bei C Geschwindigkeit läuft. Schleifen über numpy Arrays ist im Vergleich dazu ineffizient.

(Etwas wie das Schlimmste, was Sie tun könnten wäre, über das Array mit einem Index mit range oder np.arange iterieren als der erste Satz in Ihrer Frage schlägt vor, aber ich bin mir nicht sicher, ob Sie das wirklich meinen.)

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 

So für diesen Fall numpy ist 4-mal schneller als mit xrange, wenn Sie es richtig machen. Abhängig von Ihrem Problem kann numpy viel schneller als eine 4- oder 5-fache Geschwindigkeit sein.

Die Antworten auf this question erklären einige weitere Vorteile der Verwendung von numpy Arrays anstelle von Python-Listen für große Datensätze.

6

Zunächst einmal, wie von @bmu, geschrieben, sollten Sie Kombinationen von vektorisierten Berechnungen, ufancs und Indizierung verwenden. Es gibt tatsächlich einige Fälle, in denen explizites Schleifen erforderlich ist, aber diese sind wirklich selten.

Wenn explizite Schleife benötigt wird, sollten Sie mit Python 2.6 und 2.7 xrange verwenden (siehe unten). Von dem, was Sie in Python 3 sagen, ist Bereich das gleiche wie xrange (gibt einen Generator zurück). Also vielleicht Bereich ist so gut für dich.

Nun, sollten Sie es versuchen, sich (mit timeit: - hier die ipython „magic-Funktion“):

%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 

Wieder, wie oben erwähnt, die meiste Zeit ist es möglich, numpy Vektor zu verwenden/Array-Formel (oder ufunc etc ...), die ac-Geschwindigkeit laufen: viel schneller. Dies könnte man als "Vektorprogrammierung" bezeichnen. Es macht das Programm einfacher zu implementieren als C (und lesbarer), aber fast genauso schnell am Ende.

+0

Danke, ich wusste nichts über die magische Funktion. – clstaudt

+3

Es gibt ein Standard-Python-'timeit'-Modul, das es ermöglicht, dasselbe ohne IPython zu machen. Aber es ist einfach einfacher, diese magische Funktion zu benutzen. –

+0

-1 weil ich denke, das ist kein guter Benchmark. Das Schleifen über ein numpy Array ist ineffizient. – bmu

Verwandte Themen