Was ist das Python-Äquivalent zu Matlabs Tic- und Toc-Funktionen ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
, dann print toc-tic
.
Was ist das Python-Äquivalent zu Matlabs Tic- und Toc-Funktionen ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
, dann print toc-tic
.
Antworten:
Abgesehen von dem, timeit
was ThiefMaster erwähnt hat, ist eine einfache Möglichkeit, dies zu tun, nur (nach dem Importieren time
):
t = time.time()
# do stuff
elapsed = time.time() - t
Ich habe eine Hilfsklasse, die ich gerne benutze:
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))
Es kann als Kontextmanager verwendet werden:
with Timer('foo_stuff'):
# do some foo
# do some stuff
Manchmal finde ich diese Technik bequemer als timeit
- alles hängt davon ab, was Sie messen möchten.
time
Befehl verwendet, um die Laufzeit von Programmen für immer zu messen, und diese Methode repliziert dies in Python-Code. Ich sehe nichts falsch daran, solange es das richtige Werkzeug für den Job ist. timeit
ist nicht immer so, und ein Profiler ist eine viel schwerere Lösung für die meisten Anforderungen
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Ohne% .2f ist es schwer zu verstehen. Danke für die tolle Idee.
elapsed = t - time.time()
statt elapsed = time.time() - t
. In letzterem ist verstrichen negativ. Ich habe diese Änderung als Bearbeitung vorgeschlagen.
elapsed = time.time() - t
die Form ist, die immer einen positiven Wert ergibt.
Ich hatte die gleiche Frage, als ich von Matlab nach Python migrierte. Mit Hilfe dieses Threads konnte ich ein genaues Analogon des Matlab tic()
und seiner toc()
Funktionen erstellen . Fügen Sie einfach den folgenden Code oben in Ihr Skript ein.
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)
Das ist es! Jetzt sind wir voll einsatzbereit tic()
und toc()
genau wie in Matlab. Beispielsweise
tic()
time.sleep(5)
toc() # returns "Elapsed time: 5.00 seconds."
Tatsächlich ist dies vielseitiger als die integrierten Matlab-Funktionen. Hier können Sie eine weitere Instanz von erstellen TicTocGenerator
, um mehrere Vorgänge zu verfolgen oder um die Dinge anders zu planen. Während wir beispielsweise ein Skript zeitlich festlegen, können wir jetzt jedes Teil des Skripts sowie das gesamte Skript separat zeitlich festlegen. (Ich werde ein konkretes Beispiel geben)
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)
Jetzt sollten Sie in der Lage sein, zwei verschiedene Dinge zeitlich zu steuern: Im folgenden Beispiel werden das gesamte Skript und Teile eines Skripts separat zeitlich festgelegt.
tic()
time.sleep(5)
tic2()
time.sleep(3)
toc2() # returns "Elapsed time 2: 5.00 seconds."
toc() # returns "Elapsed time: 8.00 seconds."
Eigentlich müssen Sie nicht einmal tic()
jedes Mal verwenden. Wenn Sie eine Reihe von Befehlen haben, die Sie zeitlich festlegen möchten, können Sie schreiben
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...
Ich hoffe das ist hilfreich.
Das absolut beste Analogon von Tic und Toc wäre, sie einfach in Python zu definieren.
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"
Dann können Sie sie verwenden als:
tic()
# do stuff
toc()
tic
und toc
, die Matlab unterstützt, nicht korrekt . Ein wenig mehr Raffinesse wäre erforderlich.
import time
Außenseite beider Funktionen entfernen , da dies möglicherweise einige Zeit dauern kann.
tic
drücken und toc
aus ihr herausspringen .
timeit.default_timer()
besser ist als time.time()
weil time.clock()
es je nach Betriebssystem besser geeignet sein könnte
Normalerweise IPython die %time
, %timeit
, %prun
und %lprun
(wenn man hat line_profiler
installiert) erfüllt meine Profilierungs Bedürfnisse ganz gut. Ein Anwendungsfall für tic-toc
ähnliche Funktionen ergab sich jedoch, als ich versuchte, Berechnungen zu profilieren, die interaktiv gesteuert wurden, dh durch die Mausbewegung des Benutzers in einer GUI. Ich hatte das Gefühl, tic
s und toc
s in den Quellen zu spammen, während interaktives Testen der schnellste Weg wäre, um die Engpässe aufzudecken. Ich habe mich für Eli Benderskys Kurs entschieden Timer
, war aber nicht ganz glücklich, da ich die Einrückung meines Codes ändern musste, was in einigen Editoren unpraktisch sein kann und das Versionskontrollsystem verwirrt. Darüber hinaus besteht möglicherweise die Notwendigkeit, die Zeit zwischen Punkten in verschiedenen Funktionen zu messen, was mit dem nicht funktionieren würdewith
Aussage. Nachdem ich viel Python-Cleverness ausprobiert habe, ist hier die einfache Lösung, die meiner Meinung nach am besten funktioniert hat:
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 dies funktioniert, indem die Startzeiten auf einem Stapel verschoben werden, funktioniert es für mehrere Ebenen von tic
s und toc
s korrekt . Es erlaubt auch, die Formatzeichenfolge der toc
Anweisung zu ändern , um zusätzliche Informationen anzuzeigen, die mir an Elis Timer
Klasse gefallen haben .
Aus irgendeinem Grund habe ich mich mit dem Overhead einer reinen Python-Implementierung befasst und deshalb auch ein C-Erweiterungsmodul getestet:
#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);
}
Dies ist für MacOSX, und ich habe Code weggelassen, um zu überprüfen, ob lvl
er der Kürze halber außerhalb der Grenzen liegt. Während sich tictoc.res()
auf meinem System eine Auflösung von etwa 50 Nanosekunden ergibt, stellte ich fest, dass der Jitter beim Messen einer Python-Anweisung leicht im Mikrosekundenbereich liegt (und viel mehr, wenn er von IPython verwendet wird). Zu diesem Zeitpunkt wird der Overhead der Python-Implementierung vernachlässigbar, sodass sie mit der gleichen Sicherheit wie die C-Implementierung verwendet werden kann.
Ich fand heraus, dass die Nützlichkeit des tic-toc
Ansatzes praktisch auf Codeblöcke beschränkt ist, deren Ausführung mehr als 10 Mikrosekunden dauert. Darunter sind Mittelungsstrategien wie in timeit
erforderlich, um eine genaue Messung zu erhalten.
Sie können tic
und toc
von verwenden ttictoc
. Installieren Sie es mit
pip install ttictoc
Und importieren Sie sie einfach wie folgt in Ihr Skript
from ttictoc import tic,toc
tic()
# Some code
print(toc())
Ich habe gerade ein Modul [tictoc.py] erstellt, um verschachtelte Tic-Token zu erreichen, was Matlab auch tut.
from time import time
tics = []
def tic():
tics.append(time())
def toc():
if len(tics)==0:
return None
else:
return time()-tics.pop()
Und so funktioniert es:
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()
Ich hoffe, es hilft.
Schauen Sie sich das timeit
Modul an. Es ist nicht wirklich gleichwertig, aber wenn sich der Code, den Sie zeitlich festlegen möchten, in einer Funktion befindet, können Sie ihn problemlos verwenden.
timeit
am besten für Benchmarks. Es muss nicht einmal eine einzelne Funktion sein, Sie können unglaublich komplexe Anweisungen übergeben.
pip install easy-tictoc
Im Code:
from tictoc import tic, toc
tic()
#Some code
toc()
Haftungsausschluss: Ich bin der Autor dieser Bibliothek.
Dies kann auch mit einem Wrapper erfolgen. Sehr allgemeine Art, Zeit zu halten.
Der Wrapper in diesem Beispielcode umschließt jede Funktion und gibt die Zeit aus, die zum Ausführen der Funktion benötigt wird:
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()
Ich habe die Antwort von @Eli Bendersky ein wenig geändert, um ctor __init__()
und dtor __del__()
für das Timing zu verwenden, damit es bequemer verwendet werden kann, ohne den ursprünglichen Code einzurücken:
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)
Setzen Sie den Timer ("blahblah") einfach an den Anfang eines lokalen Bereichs. Die verstrichene Zeit wird am Ende des Bereichs gedruckt:
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
Es druckt aus:
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
sie nach dem letzten Aufruf nicht gelöscht wird, wenn nach der for
Schleife ein anderer Code folgt . Um den letzten Timer-Wert zu erhalten, sollte der timer
After-the- for
Loop gelöscht oder überschrieben werden , z timer = None
. B. via .
Aktualisierung von Elis Antwort auf 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)
Genau wie bei Eli kann es als Kontextmanager verwendet werden:
import time
with Timer('Count'):
for i in range(0,10_000_000):
pass
Ausgabe:
[Count] Elapsed: 0.27 seconds
Ich habe es auch aktualisiert, um die gemeldeten Zeiteinheiten (Sekunden) zu drucken und die Anzahl der Stellen zu verringern, wie von Can vorgeschlagen, und mit der Option, auch an eine Protokolldatei anzuhängen. Sie müssen datetime importieren, um die Protokollierungsfunktion verwenden zu können:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
Aufbauend auf den Antworten von Stefan und Antonimmo habe ich am Ende gesetzt
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 einem utils.py
Modul, und ich benutze es mit einem
from utils import Tictoc
tic, toc = Tictoc()
Diesen Weg
tic()
, toc()
und nisten sie mögen in Matlabtic(1)
, toc(1)
oder tic('very-important-block')
, toc('very-important-block')
und Timer mit unterschiedlichen Namen stören nicht(Hier druckt toc die verstrichene Zeit nicht aus, sondern gibt sie zurück.)
tic = time.time()
undtoc = time.time()
dann,print toc-tic, 'sec Elapsed'
wie die Leute unten gesagt haben,timeit
ist es jedoch robuster.