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 timeit
quello 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.
time
comando 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. timeit
non è 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() - t
sia 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 TicTocGenerator
per 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()
tic
e toc
, che Matlab supporta. Sarebbe richiesto un po 'più di raffinatezza.
import time
esterno di entrambe le funzioni, poiché potenzialmente può richiedere un po 'di tempo.
tic
spinga ad esso ed toc
esca 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
, %prun
e %lprun
(se si è line_profiler
installato) soddisfare i miei bisogni di profilazione abbastanza bene. Tuttavia, un caso d'uso per tic-toc
funzionalità 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 tic
s e toc
s nelle fonti durante il test interattivo sarebbe stato il modo più veloce per rivelare i colli di bottiglia. Sono andato con la Timer
classe 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'estensionewith
dichiarazione. 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 tic
s e toc
s. Permette anche di cambiare la stringa di formato dell'istruzione toc
per visualizzare informazioni aggiuntive, cosa che mi è piaciuta della Timer
classe 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-toc
dell'approccio-è praticamente limitata ai blocchi di codice che richiedono più di 10 microsecondi per essere eseguiti. Al di sotto di questo, timeit
sono necessarie strategie di media come in per ottenere una misurazione fedele.
Puoi usare tic
e toc
da 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 timeit
modulo. 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
timer
non viene cancellato dopo l'ultima chiamata, se qualsiasi altro codice segue dopo il for
ciclo. Per ottenere l'ultimo valore del timer, è necessario eliminare o sovrascrivere il timer
dopo il for
ciclo, 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.py
modulo 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.