2015-02-22 7 views
16

Ich war Benchmarking einige Python-Code bemerkte ich etwas seltsam. Ich habe die folgende Funktion zu messen, wie schnell es durch eine leere for-Schleife zu durchlaufen hat:Warum sind Pythons for-Schleifen für große Eingaben nichtlinear?

def f(n): 
    t1 = time.time() 
    for i in range(n): 
     pass 
    print(time.time() - t1) 

f(10**6) Prints 0.035, f(10**7) über 0.35, f(10**8) über 3.5 und f(10**9) über 35. Aber f(10**10)? Weit über 2000. Das ist sicherlich unerwartet. Warum sollte es mehr als 60 Mal so lange dauern, um 10 mal so viele Elemente zu durchlaufen? Was ist mit Pythons For-Schleifen, die das verursacht? Ist das Python-spezifisch, oder tritt das in vielen Sprachen auf?

+7

Sie erstellen eine Liste, wenn Sie Python2 verwenden, Ihr Timing wäre auch besser mit dem Timeit-Modul –

+2

von '10 ** 6' bis' 10 ** 9' gibt es einen großen Unterschied. _ Exponentielles Wachstum_ – levi

+2

python2 oder python3? – fvannee

Antwort

20

Wenn Sie über 10^9 erhalten Sie aus dem 32-Bit-Ganzzahlbereich. Python3 bewegt Sie dann transparent auf arbitrary precision integers, die viel langsamer zuzuweisen und zu verwenden sind.

Im Allgemeinen ist das Arbeiten mit solchen großen Zahlen einer der Bereiche, in denen Python3 viel langsamer ist als Python2 (der zumindest auf vielen Systemen schnelle 64-Bit-Integer hatte). Auf der anderen Seite macht es Python einfacher zu verwenden, mit weniger Fehlern overflow.

+2

Es begann mit Pep237: https://www.python.org/dev/peps/pep-0237/, die longs willkürliche Präzision machte. Später wurde Python3 von dem Int-Typ befreit, der die Dinge verlangsamte. Während der 3.x-Veröffentlichungen glaube ich, dass sie daran gearbeitet haben, mehr Optimierungen für kleinere Ganzzahlen einzuführen. –

+1

Der tatsächliche Unterschied in der Laufzeit scheint vollständig plattformspezifisch zu sein. –

+0

@PadraicCunningham Ich habe versucht, den Quellcode für die lange Implementierung zu lesen, um genau zu sehen, welche Optimierungen wann gemacht werden.Es gibt sicherlich die Wahl, ob eine Ziffer 15 oder 30 Bit sein sollte, aber danach wurde es viel Arbeit, alles zu entziffern. –

5

Einige genauen Timings timeit Verwendung zeigen die Zeiten in Zeile tatsächlich erhöhen etwa mit der Eingangsgröße, so dass Ihre Timings scheinen aus recht weit zu sein:

In [2]: for n in [10**6,10**7,10**8,10**9,10**10]: 
       % timeit f(n) 
    ...:  
10 loops, best of 3: 22.8 ms per loop 
1 loops, best of 3: 226 ms per loop # roughly ten times previous 
1 loops, best of 3: 2.26 s per loop # roughly ten times previous 
1 loops, best of 3: 23.3 s per loop # roughly ten times previous 
1 loops, best of 3: 4min 18s per loop # roughly ten times previous 

Mit xrange und python2 wir das Verhältnis in etwa gleich sehen offensichtlich python2 ist viel schneller insgesamt aufgrund der Tatsache, python3 int durch lange ersetzt wurde:

In [5]: for n in [10**6,10**7,10**8,10**9,10**10]: 
       % timeit f(n) 
    ...:  
100 loops, best of 3: 11.3 ms per loop 
10 loops, best of 3: 113 ms per loop 
1 loops, best of 3: 1.13 s per loop 
1 loops, best of 3: 11.4 s per loop 
1 loops, best of 3: 1min 56s per loop 

der tatsächliche Unterschied in der Laufzeit scheint als direkt auf die Größe der window's long eher verwandt zu sein ly verwandt mit Python 3. Der Unterschied ist marginal, wenn man unix benutzt, das sehnt sich viel anders als Windows, so ist dies ein plattformspezifisches Problem, wenn nicht mehr als ein Python.

+0

Ich lief einen weiteren Test, und ich erhielt die folgenden Ergebnisse: '10 ** 6' - 0,07520970538367432 Sekunden, '10 ** 7' - ,36399144430744984 Sekunden, ' 10 ** 8' - 3,492611703306957 Sekunden, ' 10 ** 9' - 34.71252936832384 Sekunden, '10 ** 10' - 2190.0514266665177 Sekunden. Könnte es ein Unterschied sein in welchem ​​System wir es ausführen? – user3002473

+0

@ user3002473. Worauf fährst du es? –

+0

@PadriacCunningham Windows 7 64-Bit-, Intel Core i5 3.20 GHz-Prozessor mit 4,00 GB RAM installiert. – user3002473

Verwandte Themen