2013-09-01 16 views
5

W nieco spreparowanym eksperymencie chciałem porównać niektóre wbudowane funkcje Pythona z funkcjami numpy. Kiedy zacząłem je wyczekiwać, znalazłem coś dziwnego.Dwa bardzo różne, ale bardzo konsekwentne wyniki z Python timeit

Kiedy pisał:

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

Chciałbym uzyskać dwa różne wyniki w prawie losowej naprzemiennie w bardzo istotny statystycznie sposób.

Zmienia się na 2 sekundy i 0,5 sekundy.

To zdezorientowało mnie, więc przeprowadziłem kilka eksperymentów, aby dowiedzieć się, co się dzieje i byłem tylko bardziej zdezorientowany. Dlatego próbowałem następujących eksperymentów:

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

który doprowadził w całości do liczby 0.5. Próbowałem posiać to z generatorem:

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

co doprowadziło do listy całkowicie wypełnionej numerem 2.0.

Na sugestię alecxe zmieniłem oświadczenie timeit do:

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

które w podobny sposób naprzemienny pomiędzy około 0,1 i 0,4 sekundy, ale kiedy reran eksperyment porównujący generatory i listowych, ale tym razem wyników zostały odwrócone. Oznacza to, że wyrażenie generatora regularnie zawierało 0,1-sekundowy numer, podczas gdy zrozumienie listy zwróciło pełną listę 0,4-sekundowego numeru.

bezpośrednie wyjście na konsolę:

>>> 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 
>>>  

Edycja: używam Ubuntu 12.04 działa DWM, i widziałem te wyniki zarówno w terminalach i gnome-terminal. Używam python 2.7.3

Czy ktoś wie, co się tutaj dzieje? Wydaje mi się to naprawdę dziwne.

+0

Co otrzymasz, jeśli przeniesiesz swoją instrukcję importu do drugiego argumentu w ten sposób: 'timeit.timeit ('math.e ** 2 ',' import matematyczny ', liczba = 1000000) '? – alecxe

+0

@alecxe Dzięki za sugestię. jeszcze bardziej dziwaczne wyniki. Publikowanie teraz. –

+0

Nie widzę czegoś podobnego, kiedy próbuję. – user2357112

Odpowiedz

0

Okazało się, że działo się tu kilka rzeczy, choć najwyraźniej niektóre z tych dziwactw są charakterystyczne dla mojej maszyny, ale uważam, że warto je opublikować na wypadek, gdyby ktoś był zdziwiony tym samym.

Po pierwsze, nie ma różnicy pomiędzy dwoma funkcjami timeit się tym, że:

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

stwierdzenia import leniwie załadowany. Staje się to oczywiste, jeśli spróbujesz następujący eksperyment:

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

versus:

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

Więc kiedy została ona bezpośrednio uruchomić w listowego wygląda to oświadczenie import był ładowany dla każdego wpisu. (Dokładne powody są prawdopodobnie związane z moją konfiguracją).

Po tym, wracając do pierwotnego pytania, wygląda na to, że 3/4 czasu faktycznie zajęło importowanie matematyki, więc domyślam się, że podczas generowania równania nie było miejsca w pamięci podręcznej między iteracjami, podczas gdy było cachowanie importowe w zrozumieniu listy (znowu, dokładna przyczyna tego jest prawdopodobnie specyficzna dla konfiguracji)

Powiązane problemy