2012-04-28 11 views
37

Komenda% timeit magic IPython wykonuje swoją pracę, mierząc czas potrzebny do uruchomienia kodu Pythona. Teraz chcę użyć czegoś analogicznego w skrypcie Pythona. Wiem o module timeit, jednak ma on kilka wad, na przykład, jak wybrać adaptacyjnie liczbę przebiegów? tj domyślny kodJak uruchomić magię IPython ze skryptu (lub czas skryptu w języku Python)?

import timeit 
t=timeit.Timer("code(f)", "from __main__ import code,f") 
t.timeit() 

uruchamia kod milion razy. Komenda% timeit IPyhton magic robi to automatycznie. Sugeruję, że mógłbym użyć czegoś takiego jak kod MATLAB http://www.mathworks.com/matlabcentral/fileexchange/18798

, który wykonuje wszystkie zadania automatycznie (a także informuje, czy narzut funkcji jest duży).

Jak mogę wywołać% timeit magic ze skryptu w Pythonie (czy może jest lepsze rozwiązanie czasu)?

+7

Jeśli stworzysz skrypt IPython (* .ipy), wówczas będzie dostępna cała składnia IPythona i możesz po prostu zrobić '% timeit foo' jak zwykle. – minrk

+1

Dziękuję, to dobra sugestia. Ale używam tego w pliku trybu org, i myślę, że wie tylko o pythonie jeszcze :) –

Odpowiedz

44

Zależy trochę od tego, którą wersję IPython masz. Jeśli masz 1.x:

from IPython import get_ipython 
ipython = get_ipython() 

Jeśli masz starszą wersję:

import IPython.core.ipapi 
ipython = IPython.core.ipapi.get() 

lub

import IPython.ipapi 
ipython = IPython.ipapi.get() 

Po dokonaniu uruchomić magiczne polecenie tak:

ipython.magic("timeit abs(-42)") 

Należy zauważyć, że skrypt musi być uruchamiany za pośrednictwem ipython.

+2

Wydaje się, że to już nie działa pod ipython 1.x – DaveP

+1

Działa to dla ipython 1.x: 'z ipython importowej get_ipython' ' ipython = get_ipython() ' – suzanshakya

+0

@suzanshakya get_ipython() wydaje się powrót Brak w instancji który wcześniej działał. umysł wskazuje na przykład? – badgley

5

Zarówno ipython i moduł timeit, gdy wywołana z python -m timeit, należy wykonać tę samą pętlę z rosnącą wartością liczby aż wynikiem rozrządu przewyższa pewien próg, który gwarantuje pomiar czasu jest przede wszystkim wolny od zakłóceń systemu operacyjnego.

Możesz porównać IPython implementation of the %timeit magic z Python timeit standard module, aby zobaczyć, że robią w większości takie same.

Odpowiadając na pytanie, powinieneś prawdopodobnie replikować tę samą pętlę, dopóki nie znajdziesz prawidłowej wartości parametru o numerze.

+0

OK, mogę po prostu skopiować "główną" część modułu timeit. Zastanawiam się, dlaczego nie jest ona zawarta w bibliotece. –

2

Poniższe działa, jeśli jeden uruchamia skrypt Python interaktywnie w IPython. Np test.py:

def f(): 
    # Algorithm 1 
    pass 

def g(): 
    # Algorithm 2 
    pass 

# which one is faster? 
mgc = get_ipython().magic 
mgc(u'%timeit f()') 
mgc(u'%timeit g()') 

Następnie uruchom go interaktywnie w ipython

%run -i test.py 

wypluć synchronizacją. Przełącznik -i jest niezbędny, aby zmienne były w zakresie. Nie wymyśliłem, jak to zrobić bez uruchamiania instancji IPython, tj. Po prostu importując timeit z IPython i używając go jako funkcji. Jednak to rozwiązanie działa w moich celach, czyli zautomatyzować niektóre przebiegi czasowe.

1

Jednym ze sposobów uruchomienia funkcji magii ipython jest prawdopodobnie użycie instancji narzędzia ipython.
Na przykład: (większość kodów są wypożyczenia ipython website)

from IPython.terminal.embed import InteractiveShellEmbed 

ipshell = InteractiveShellEmbed() 
ipshell.dummy_mode = True 
print('\nTrying to call IPython which is now "dummy":') 
ipshell.magic("%timeit abs(-42)"); 
ipshell() 
print('Nothing happened...') 

może działać za pomocą pytona interpretera
PS pomocą dummy_mode zapobiegnie wywoływania interaktywnej powłoki.

+1

'from IPython import get_ipython; ipython = get_ipython() 'zwraca" AttributeError: 'NoneType' "w wersji 4.2.0, ale wydaje się, że działa dobrze. – 16num

1

Według documentation modułu timeit.py, gdy timeit jest prowadzony w trybie wiersza poleceń,

If -n is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds.

To co robi ipython. Dlatego liczba pętli jest zawsze potęgą 10. Można zrobić coś podobnego w swoim własnym kodem osadzając wezwanie do t.timeit() wewnątrz pętli, która sprawia, że ​​na pewno nie czekać zbyt długo:

import timeit 
t = timeit.Timer("code(f)", "from __main__ import code, f") 

max_time = 0.2 
N = 0 
curr_time = t.timeit(1) 

while curr_time < max_time: 
    N += 1 
    curr_time = t.timeit(10**N) 

mean_time = curr_time/float(10**N) 

Zapewni to, że czas profilowania wynosi co najmniej 0,2 sekundy, ale nie znacznie więcej --- chyba że wywołanie funkcji raz zajmuje dużo czasu.

Powiązane problemy