Jaki jest odpowiednik w Pythonie funkcji tic i toc Matlaba ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
then print toc-tic
.
Jaki jest odpowiednik w Pythonie funkcji tic i toc Matlaba ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
then print toc-tic
.
Odpowiedzi:
Poza timeit
tym, o czym wspomniał ThiefMaster, prostym sposobem na to jest po prostu (po imporcie time
):
t = time.time()
# do stuff
elapsed = time.time() - t
Mam klasę pomocniczą, której lubię używać:
class Timer(object):
def __init__(self, name=None):
self.name = name
def __enter__(self):
self.tstart = time.time()
def __exit__(self, type, value, traceback):
if self.name:
print('[%s]' % self.name,)
print('Elapsed: %s' % (time.time() - self.tstart))
Może być używany jako menedżer kontekstu:
with Timer('foo_stuff'):
# do some foo
# do some stuff
Czasami uważam tę technikę za wygodniejszą niż timeit
- wszystko zależy od tego, co chcesz zmierzyć.
time
polecenia unix do mierzenia czasu wykonywania programów, a ta metoda powiela to w kodzie Pythona. Nie widzę w tym nic złego, o ile jest to właściwe narzędzie do pracy. timeit
nie zawsze tak jest, a profiler jest znacznie cięższym rozwiązaniem dla większości potrzeb
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Trudno to zrozumieć bez% .2f. Dzięki za świetny pomysł.
elapsed = t - time.time()
, zamiast elapsed = time.time() - t
. W tym ostatnim upłynął będzie ujemny. Zaproponowałem tę zmianę jako edycję.
elapsed = time.time() - t
jest to forma, która zawsze daje wartość dodatnią.
Miałem to samo pytanie, kiedy migrowałem do Pythona z Matlab. Z pomocą tego wątku udało mi się skonstruować dokładny odpowiednik Matlaba tic()
i toc()
funkcji. Po prostu wstaw następujący kod u góry skryptu.
import time
def TicTocGenerator():
# Generator that returns time differences
ti = 0 # initial time
tf = time.time() # final time
while True:
ti = tf
tf = time.time()
yield tf-ti # returns the time difference
TicToc = TicTocGenerator() # create an instance of the TicTocGen generator
# This will be the main function through which we define both tic() and toc()
def toc(tempBool=True):
# Prints the time difference yielded by generator instance TicToc
tempTimeInterval = next(TicToc)
if tempBool:
print( "Elapsed time: %f seconds.\n" %tempTimeInterval )
def tic():
# Records a time in TicToc, marks the beginning of a time interval
toc(False)
Otóż to! Teraz jesteśmy gotowi do pełnego wykorzystania tic()
i toc()
tak jak w Matlabie. Na przykład
tic()
time.sleep(5)
toc() # returns "Elapsed time: 5.00 seconds."
W rzeczywistości jest to bardziej wszechstronne niż wbudowane funkcje Matlab. Tutaj możesz utworzyć kolejną instancję, TicTocGenerator
aby śledzić wiele operacji lub po prostu inaczej mierzyć czas. Na przykład, podczas odmierzania czasu skryptu, możemy teraz określić czas dla każdego fragmentu skryptu oddzielnie, a także dla całego skryptu. (Podam konkretny przykład)
TicToc2 = TicTocGenerator() # create another instance of the TicTocGen generator
def toc2(tempBool=True):
# Prints the time difference yielded by generator instance TicToc2
tempTimeInterval = next(TicToc2)
if tempBool:
print( "Elapsed time 2: %f seconds.\n" %tempTimeInterval )
def tic2():
# Records a time in TicToc2, marks the beginning of a time interval
toc2(False)
Teraz powinieneś być w stanie zmierzyć czas w dwóch osobnych rzeczach: W poniższym przykładzie oddzielnie mierzymy czas dla całego skryptu i części skryptu.
tic()
time.sleep(5)
tic2()
time.sleep(3)
toc2() # returns "Elapsed time 2: 5.00 seconds."
toc() # returns "Elapsed time: 8.00 seconds."
Właściwie nie musisz nawet używać za tic()
każdym razem. Jeśli masz serię poleceń, które chcesz mierzyć czas, możesz napisać
tic()
time.sleep(1)
toc() # returns "Elapsed time: 1.00 seconds."
time.sleep(2)
toc() # returns "Elapsed time: 2.00 seconds."
time.sleep(3)
toc() # returns "Elapsed time: 3.00 seconds."
# and so on...
Mam nadzieję, że jest to pomocne.
Absolutnie najlepszym analogiem tic i toc byłoby po prostu zdefiniowanie ich w Pythonie.
def tic():
#Homemade version of matlab tic and toc functions
import time
global startTime_for_tictoc
startTime_for_tictoc = time.time()
def toc():
import time
if 'startTime_for_tictoc' in globals():
print "Elapsed time is " + str(time.time() - startTime_for_tictoc) + " seconds."
else:
print "Toc: start time not set"
Następnie możesz ich użyć jako:
tic()
# do stuff
toc()
tic
i toc
, które obsługuje Matlab. Wymagane byłoby trochę więcej wyrafinowania.
import time
zewnętrzną stronę obu funkcji, ponieważ może to zająć trochę czasu.
tic
pushować i toc
wyskakiwać z niej.
timeit.default_timer()
jest to lepsze niż time.time()
ponieważ time.clock()
może być bardziej odpowiednie w zależności od systemu operacyjnego
Zazwyczaj ipython na %time
, %timeit
, %prun
oraz %lprun
(jeśli jest line_profiler
zainstalowany) spełniają moje potrzeby profilowania całkiem dobrze. Jednak przypadek użycia tic-toc
funkcji-like pojawił się, gdy próbowałem profilować obliczenia, które były interaktywnie sterowane, tj. Przez ruch myszy użytkownika w GUI. Czułem, że spamowanie tic
i spamowanie toc
w źródłach podczas interaktywnego testowania byłoby najszybszym sposobem na ujawnienie wąskich gardeł. Poszedłem z Timer
klasą Eli Bendersky'ego , ale nie byłem w pełni zadowolony, ponieważ wymagało to zmiany wcięcia mojego kodu, co może być niewygodne w niektórych edytorach i dezorientuje system kontroli wersji. Ponadto może zaistnieć potrzeba pomiaru czasu między punktami w różnych funkcjach, które nie działałyby zwith
komunikat. Po wypróbowaniu dużej ilości sprytu w Pythonie, oto proste rozwiązanie, które według mnie działa najlepiej:
from time import time
_tstart_stack = []
def tic():
_tstart_stack.append(time())
def toc(fmt="Elapsed: %s s"):
print fmt % (time() - _tstart_stack.pop())
Ponieważ działa to poprzez przesuwanie czasów rozpoczęcia na stosie, będzie działać poprawnie na wielu poziomach tic
si toc
s. Pozwala również zmienić ciąg formatu toc
instrukcji, aby wyświetlić dodatkowe informacje, które podobały mi się w Timer
klasie Eli .
Z jakiegoś powodu martwiłem się o narzuty związane z czystą implementacją Pythona, więc przetestowałem również moduł rozszerzenia C:
#include <Python.h>
#include <mach/mach_time.h>
#define MAXDEPTH 100
uint64_t start[MAXDEPTH];
int lvl=0;
static PyObject* tic(PyObject *self, PyObject *args) {
start[lvl++] = mach_absolute_time();
Py_RETURN_NONE;
}
static PyObject* toc(PyObject *self, PyObject *args) {
return PyFloat_FromDouble(
(double)(mach_absolute_time() - start[--lvl]) / 1000000000L);
}
static PyObject* res(PyObject *self, PyObject *args) {
return tic(NULL, NULL), toc(NULL, NULL);
}
static PyMethodDef methods[] = {
{"tic", tic, METH_NOARGS, "Start timer"},
{"toc", toc, METH_NOARGS, "Stop timer"},
{"res", res, METH_NOARGS, "Test timer resolution"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
inittictoc(void) {
Py_InitModule("tictoc", methods);
}
To jest dla MacOSX i pominąłem kod, aby sprawdzić, czy lvl
jest poza zakresem dla zwięzłości. Chociaż tictoc.res()
zapewnia rozdzielczość około 50 nanosekund w moim systemie, odkryłem, że jitter pomiaru dowolnej instrukcji Pythona z łatwością mieści się w zakresie mikrosekund (i znacznie więcej, gdy jest używany z IPythona). W tym momencie narzut implementacji Pythona staje się pomijalny, dzięki czemu można go używać z takim samym zaufaniem jak implementacja C.
Okazało się, że użyteczność metody tic-toc
-podejścia jest praktycznie ograniczona do bloków kodu, których wykonanie zajmuje więcej niż 10 mikrosekund. Poniżej, timeit
aby uzyskać wierny pomiar, wymagane są strategie uśredniania, takie jak w .
Możesz używać tic
i toc
od ttictoc
. Zainstaluj go z
pip install ttictoc
I po prostu zaimportuj je do swojego skryptu w następujący sposób
from ttictoc import tic,toc
tic()
# Some code
print(toc())
Właśnie utworzyłem moduł [tictoc.py] do tworzenia zagnieżdżonych tików, co robi Matlab.
from time import time
tics = []
def tic():
tics.append(time())
def toc():
if len(tics)==0:
return None
else:
return time()-tics.pop()
I to działa w ten sposób:
from tictoc import tic, toc
# This keeps track of the whole process
tic()
# Timing a small portion of code (maybe a loop)
tic()
# -- Nested code here --
# End
toc() # This returns the elapse time (in seconds) since the last invocation of tic()
toc() # This does the same for the first tic()
Mam nadzieję, że to pomoże.
Przyjrzyj się timeit
modułowi. Nie jest to tak naprawdę równoważne, ale jeśli kod, który chcesz mierzyć czas, znajduje się wewnątrz funkcji, możesz go łatwo użyć.
timeit
najlepiej sprawdza się w testach porównawczych. Nie musi to być nawet pojedyncza funkcja, możesz przekazywać bardzo złożone instrukcje.
pip install easy-tictoc
W kodzie:
from tictoc import tic, toc
tic()
#Some code
toc()
Zastrzeżenie: jestem autorem tej biblioteki.
Można to również zrobić za pomocą opakowania. Bardzo ogólny sposób na trzymanie czasu.
Opakowanie w tym przykładowym kodzie otacza dowolną funkcję i wyświetla ilość czasu potrzebną do wykonania funkcji:
def timethis(f):
import time
def wrapped(*args, **kwargs):
start = time.time()
r = f(*args, **kwargs)
print "Executing {0} took {1} seconds".format(f.func_name, time.time()-start)
return r
return wrapped
@timethis
def thistakestime():
for x in range(10000000):
pass
thistakestime()
Zmieniłem trochę odpowiedź @Eli Bendersky, aby użyć ctor __init__()
i dtor __del__()
do pomiaru czasu, aby można było z niego wygodniej korzystać bez wcięcia oryginalnego kodu:
class Timer(object):
def __init__(self, name=None):
self.name = name
self.tstart = time.time()
def __del__(self):
if self.name:
print '%s elapsed: %.2fs' % (self.name, time.time() - self.tstart)
else:
print 'Elapsed: %.2fs' % (time.time() - self.tstart)
Aby użyć, po prostu umieść Timer („blahblah”) na początku jakiegoś lokalnego zakresu. Upływający czas zostanie wydrukowany na końcu zakresu:
for i in xrange(5):
timer = Timer("eigh()")
x = numpy.random.random((4000,4000));
x = (x+x.T)/2
numpy.linalg.eigh(x)
print i+1
timer = None
Drukuje:
1
eigh() elapsed: 10.13s
2
eigh() elapsed: 9.74s
3
eigh() elapsed: 10.70s
4
eigh() elapsed: 10.25s
5
eigh() elapsed: 11.28s
timer
nie jest ona usuwana po ostatnim wywołaniu, jeśli po for
pętli występuje inny kod . Aby uzyskać ostatnią wartość timera, należy usunąć lub nadpisać timer
po for
pętli, na przykład poprzez timer = None
.
Aktualizacja odpowiedzi Eli do Pythona 3:
class Timer(object):
def __init__(self, name=None, filename=None):
self.name = name
self.filename = filename
def __enter__(self):
self.tstart = time.time()
def __exit__(self, type, value, traceback):
message = 'Elapsed: %.2f seconds' % (time.time() - self.tstart)
if self.name:
message = '[%s] ' % self.name + message
print(message)
if self.filename:
with open(self.filename,'a') as file:
print(str(datetime.datetime.now())+": ",message,file=file)
Podobnie jak Eli, może być używany jako menedżer kontekstu:
import time
with Timer('Count'):
for i in range(0,10_000_000):
pass
Wynik:
[Count] Elapsed: 0.27 seconds
Zaktualizowałem go również, aby drukować zgłaszane jednostki czasu (sekundy) i zmniejszać liczbę cyfr zgodnie z sugestią Can, a także z opcją dołączania do pliku dziennika. Aby korzystać z funkcji rejestrowania, musisz zaimportować datę i godzinę:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
Opierając się na odpowiedziach Stefana i antonimmo, skończyło się umieszczaniem
def Tictoc():
start_stack = []
start_named = {}
def tic(name=None):
if name is None:
start_stack.append(time())
else:
start_named[name] = time()
def toc(name=None):
if name is None:
start = start_stack.pop()
else:
start = start_named.pop(name)
elapsed = time() - start
return elapsed
return tic, toc
w utils.py
module i używam go z plikiem
from utils import Tictoc
tic, toc = Tictoc()
Tą drogą
tic()
, toc()
a gniazdo nich jak w Matlabtic(1)
, toc(1)
lub tic('very-important-block')
, toc('very-important-block')
i timery z różnymi nazwami nie będzie kolidować(tutaj toc nie drukuje czasu, który upłynął, ale zwraca go).
tic = time.time()
atoc = time.time()
,print toc-tic, 'sec Elapsed'
jak powiedzieli ludzie poniżej,timeit
jest jednak bardziej wytrzymały.