2013-09-01 11 views
5

In un esperimento un po 'forzato, ho voluto confrontare alcune delle funzioni incorporate di Python con quelle di Numpy. Quando ho iniziato a crearli, ho trovato qualcosa di bizzarro.Due risultati molto diversi ma molto coerenti da Python timeit

quando ho scritto il seguente:

import timeit 
timeit.timeit('import math; math.e**2', number=1000000) 

vorrei ottenere due risultati diversi in alternanza quasi a caso in un modo molto statisticamente significativo.

Questo si alterna tra 2 secondi e 0,5 secondi.

Questo mi ha confuso, così ho fatto alcuni esperimenti per capire cosa stava succedendo e io ero solo più confuso. Così ho provato i seguenti esperimenti:

[timeit.timeit('import math; math.e**2', number=1000000) for i in xrange(100)] 

che hanno portato tutto al numero 0.5. Ho quindi provato a seminare questo con un generatore:

test = (timeit.timeit('import math; math.e**2', number=1000000) for i in xrange(100)) 
[item for item in test] 

che ha portato a un elenco interamente completo del numero 2.0.

Su suggerimento di alecxe ho cambiato la mia dichiarazione timeit a:

timeit.timeit('math.e**2', 'import math', number=1000000) 

che allo stesso modo alternato tra circa 0,1 e 0,4 secondi, ma quando ho reran l'esperimento confrontando generatori e list comprehension, ma questa volta i risultati sono stati capovolti. Ciò vuol dire che l'espressione del generatore generava regolarmente il numero di 0,1 secondi, mentre la comprensione della lista restituiva un elenco completo del numero di 0,4 secondi.

diretto output della console:

>>> test = (timeit.timeit('math.e**2', 'import math', number=1000000) for i in xrange(100)) 
>>> test.next() 
0.15114784240722656 

>>> timeit.timeit('math.e**2', 'import math', number=1000000) 
0.44176197052001953 
>>>  

Edit: sto usando Ubuntu 12.04 in esecuzione DWM, e ho visto questi risultati sia in xterm e un gnome-terminal. Sto usando python 2.7.3

Qualcuno sa cosa sta succedendo qui? Questo mi sembra davvero strano.

+0

Cosa ottieni se sposti la tua istruzione import sul secondo argomento come questo: 'timeit.timeit ('math.e ** 2 ',' import math ', number = 1000000) '? – alecxe

+0

@alecxe Grazie per il suggerimento. risultati ancora più bizzarri. Pubblicare ora. –

+0

Non vedo nulla di simile quando lo provo. – user2357112

risposta

0

Si è verificato un paio di cose che accadono qui, anche se apparentemente alcuni di questi capricci sono specifici per la mia macchina, ma tuttavia penso che valga la pena pubblicarli nel caso in cui qualcuno sia perplesso dalla stessa cosa.

Innanzitutto, c'è una differenza tra le due funzioni timeit dal fatto che la:

timeit.timeit('math.e**2', 'import math', number=1000000) 

prospetti importazione pigramente caricamento. Questo diventa evidente se si tenta il seguente esperimento:

timeit.timeit('1+1', 'import math', number=1000000) 

versus:

timeit.timeit('1+1', number=1000000) 

Così, quando è stato eseguito direttamente nella comprensione lista sembra che questa dichiarazione di importazione è stata caricata per ogni ingresso. (Motivi esatti per questo sono probabilmente correlati alla mia configurazione).

Passato che, tornando alla domanda originale, sembra che 3/4 del tempo sia stato effettivamente impiegato per importare la matematica, quindi suppongo che quando è stata generata l'equazione, non ci fosse memoria cache tra le iterazioni, mentre c'era un caching di importazione nella comprensione della lista (di nuovo, la ragione esatta per questa è probabilmente specifica della configurazione)