Qual è l'equivalente Python delle funzioni tic e toc di Matlab ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()then print toc-tic.
Qual è l'equivalente Python delle funzioni tic e toc di Matlab ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()then print toc-tic.
Risposte:
A parte timeitquello menzionato da ThiefMaster, un modo semplice per farlo è solo (dopo l'importazione time):
t = time.time()
# do stuff
elapsed = time.time() - t
Ho una classe di supporto che mi piace usare:
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))
Può essere utilizzato come gestore di contesto:
with Timer('foo_stuff'):
# do some foo
# do some stuff
A volte trovo questa tecnica più comoda di timeit- tutto dipende da ciò che vuoi misurare.
timecomando unix per misurare i tempi di esecuzione dei programmi e questo metodo lo replica all'interno del codice Python. Non ci vedo niente di sbagliato, purché sia lo strumento giusto per il lavoro. timeitnon è sempre così, e un profiler è una soluzione molto più pesante per la maggior parte delle esigenze
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'. È difficile da capire senza% .2f. Grazie per l'ottima idea.
elapsed = t - time.time(), invece di elapsed = time.time() - t. In quest'ultimo trascorso sarà negativo. Ho suggerito questa modifica come modifica.
elapsed = time.time() - tsia la forma che dà sempre un valore positivo.
Ho avuto la stessa domanda quando sono migrato a Python da Matlab. Con l'aiuto di questo thread sono stato in grado di costruire un analogo esatto di Matlab tic()e toc()funzioni. Inserisci semplicemente il codice seguente all'inizio dello script.
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)
Questo è tutto! Ora siamo pronti per l'uso completo tic()e toc()proprio come in Matlab. Per esempio
tic()
time.sleep(5)
toc() # returns "Elapsed time: 5.00 seconds."
In realtà, questo è più versatile delle funzioni Matlab integrate. Qui, puoi creare un'altra istanza di TicTocGeneratorper tenere traccia di più operazioni o semplicemente per temporizzare le cose in modo diverso. Ad esempio, durante il cronometraggio di uno script, ora possiamo cronometrare separatamente ogni parte dello script, così come l'intero script. (Fornirò un esempio concreto)
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)
Ora dovresti essere in grado di cronometrare due cose separate: Nell'esempio seguente, cronometriamo lo script totale e le parti di uno script separatamente.
tic()
time.sleep(5)
tic2()
time.sleep(3)
toc2() # returns "Elapsed time 2: 5.00 seconds."
toc() # returns "Elapsed time: 8.00 seconds."
In realtà, non è nemmeno necessario utilizzarlo tic()ogni volta. Se hai una serie di comandi che vuoi cronometrare, puoi scrivere
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...
Spero che questo sia di aiuto.
Il miglior analogo in assoluto di tic e toc sarebbe semplicemente definirli in python.
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"
Quindi puoi usarli come:
tic()
# do stuff
toc()
tice toc, che Matlab supporta. Sarebbe richiesto un po 'più di raffinatezza.
import timeesterno di entrambe le funzioni, poiché potenzialmente può richiedere un po 'di tempo.
ticspinga ad esso ed tocesca da esso.
timeit.default_timer()è meglio che time.time()perché time.clock()potrebbe essere più appropriato a seconda del sistema operativo
Di solito, IPython di %time, %timeit, %prune %lprun(se si è line_profilerinstallato) soddisfare i miei bisogni di profilazione abbastanza bene. Tuttavia, un caso d'uso per tic-tocfunzionalità simili è emerso quando ho cercato di profilare calcoli guidati in modo interattivo, cioè dal movimento del mouse dell'utente in una GUI. Sentivo che lo spamming di tics e tocs nelle fonti durante il test interattivo sarebbe stato il modo più veloce per rivelare i colli di bottiglia. Sono andato con la Timerclasse di Eli Bendersky , ma non ero completamente soddisfatto, poiché mi ha richiesto di modificare il rientro del mio codice, il che può essere scomodo in alcuni editor e confondere il sistema di controllo delle versioni. Inoltre, potrebbe essere necessario misurare il tempo tra i punti in diverse funzioni, che non funzionerebbero con l'estensionewithdichiarazione. Dopo aver provato un sacco di intelligenza Python, ecco la semplice soluzione che ho trovato funzionava meglio:
from time import time
_tstart_stack = []
def tic():
_tstart_stack.append(time())
def toc(fmt="Elapsed: %s s"):
print fmt % (time() - _tstart_stack.pop())
Da questa opere spingendo l'orario di inizio su una pila, che possa funzionare correttamente per diversi livelli di tics e tocs. Permette anche di cambiare la stringa di formato dell'istruzione tocper visualizzare informazioni aggiuntive, cosa che mi è piaciuta della Timerclasse di Eli .
Per qualche motivo mi sono preoccupato del sovraccarico di un'implementazione Python pura, quindi ho testato anche un modulo di estensione 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);
}
Questo è per MacOSX e ho omesso il codice per verificare se lvlè fuori dai limiti per brevità. Sebbene tictoc.res()produca una risoluzione di circa 50 nanosecondi sul mio sistema, ho scoperto che il jitter della misurazione di qualsiasi istruzione Python è facilmente dell'ordine dei microsecondi (e molto di più se usato da IPython). A questo punto, il sovraccarico dell'implementazione di Python diventa trascurabile, in modo che possa essere utilizzato con la stessa sicurezza dell'implementazione C.
Ho scoperto che l'utilità tic-tocdell'approccio-è praticamente limitata ai blocchi di codice che richiedono più di 10 microsecondi per essere eseguiti. Al di sotto di questo, timeitsono necessarie strategie di media come in per ottenere una misurazione fedele.
Puoi usare tice tocda ttictoc. Installalo con
pip install ttictoc
E importali nel tuo script come segue
from ttictoc import tic,toc
tic()
# Some code
print(toc())
Ho appena creato un modulo [tictoc.py] per ottenere tic toc annidati, che è ciò che fa Matlab.
from time import time
tics = []
def tic():
tics.append(time())
def toc():
if len(tics)==0:
return None
else:
return time()-tics.pop()
E funziona in questo modo:
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()
Spero possa essere d'aiuto.
Dai un'occhiata al timeitmodulo. Non è proprio equivalente ma se il codice che vuoi cronometrare è all'interno di una funzione puoi usarlo facilmente.
timeitè il migliore per i benchmark. Non deve nemmeno essere una singola funzione, puoi passare istruzioni complesse in modo anomalo.
pip install easy-tictoc
Nel codice:
from tictoc import tic, toc
tic()
#Some code
toc()
Disclaimer: sono l'autore di questa libreria.
Questo può essere fatto anche usando un wrapper. Modo molto generale di tenere il tempo.
Il wrapper in questo codice di esempio racchiude qualsiasi funzione e stampa la quantità di tempo necessaria per eseguire la funzione:
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()
Ho cambiato un po 'la risposta di @Eli Bendersky per usare ctor __init__()e dtor __del__()per fare il tempismo, in modo che possa essere usato più comodamente senza indentare il codice originale:
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)
Per usarlo, metti semplicemente Timer ("blahblah") all'inizio di un ambito locale. Il tempo trascorso verrà stampato alla fine dell'ambito:
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
Stampa:
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
timernon viene cancellato dopo l'ultima chiamata, se qualsiasi altro codice segue dopo il forciclo. Per ottenere l'ultimo valore del timer, è necessario eliminare o sovrascrivere il timerdopo il forciclo, ad esempio tramite timer = None.
Aggiornamento della risposta di Eli a Python 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)
Proprio come quello di Eli, può essere utilizzato come gestore di contesto:
import time
with Timer('Count'):
for i in range(0,10_000_000):
pass
Produzione:
[Count] Elapsed: 0.27 seconds
L'ho anche aggiornato per stampare le unità di tempo riportate (secondi) e tagliare il numero di cifre come suggerito da Can, e con la possibilità di aggiungerlo anche a un file di registro. È necessario importare datetime per utilizzare la funzione di registrazione:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
Basandomi sulle risposte di Stefan e antonimmo, ho finito per mettere
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
in un utils.pymodulo e lo uso con un file
from utils import Tictoc
tic, toc = Tictoc()
Per di qua
tic(), toc()e nidificano loro come in Matlabtic(1), toc(1)o tic('very-important-block'), toc('very-important-block')e timer con nomi diversi non interferire(qui toc non stampa il tempo trascorso, ma lo restituisce.)
tic = time.time()etoc = time.time(), quindiprint toc-tic, 'sec Elapsed'come la gente ha detto di seguito, però,timeitè più robusto.