Який еквівалент Python функцій tic та toc Matlab ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
, то print toc-tic
.
Який еквівалент Python функцій tic та toc Matlab ?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
, то print toc-tic
.
Відповіді:
Крім того, про timeit
який згадував ThiefMaster, простий спосіб зробити це просто (після імпорту time
):
t = time.time()
# do stuff
elapsed = time.time() - t
У мене є клас помічників, який я люблю використовувати:
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))
Його можна використовувати як менеджер контексту:
with Timer('foo_stuff'):
# do some foo
# do some stuff
Іноді мені ця техніка зручніша, ніж timeit
- все залежить від того, що ти хочеш виміряти.
time
для вимірювання часу виконання програм назавжди, і цей метод копіює це всередині коду Python. Я не бачу в цьому нічого поганого, якщо це правильний інструмент для роботи. timeit
не завжди це, і профайлер - це набагато більш важке рішення для більшості потреб
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Важко зрозуміти без% .2f. Дякую за чудову ідею.
elapsed = t - time.time()
замість цього elapsed = time.time() - t
. В останньому минулий буде негативним. Я запропонував цю зміну змінити.
elapsed = time.time() - t
це форма, яка завжди дає позитивне значення.
У мене було те саме питання, коли я перейшов на пітон з Матлаба. За допомогою цієї нитки мені вдалося побудувати точний аналог Matlab tic()
та toc()
функцій. Просто вставте наступний код у верхній частині сценарію.
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)
Це воно! Тепер ми готові до повного використання tic()
і так toc()
само, як у Matlab. Наприклад
tic()
time.sleep(5)
toc() # returns "Elapsed time: 5.00 seconds."
Насправді це більш універсально, ніж вбудовані функції Matlab. Тут ви можете створити інший примірник TicTocGenerator
для відстеження кількох операцій або просто провести час по-різному. Наприклад, під час вибору сценарію ми тепер можемо окремо розраховувати кожен фрагмент сценарію окремо, як і весь сценарій. (Я надам конкретний приклад)
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)
Тепер ви маєте змогу обміняти дві окремі речі: У наступному прикладі ми загадуємо загальний сценарій та частини сценарію окремо.
tic()
time.sleep(5)
tic2()
time.sleep(3)
toc2() # returns "Elapsed time 2: 5.00 seconds."
toc() # returns "Elapsed time: 8.00 seconds."
Власне, вам навіть не потрібно tic()
кожен раз користуватися. Якщо у вас є ряд команд, які ви хочете вчасно, тоді ви можете написати
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...
Я сподіваюся, що це корисно.
Абсолютним найкращим аналогом tic і toc було б просто визначити їх у 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"
Тоді ви можете використовувати їх як:
tic()
# do stuff
toc()
tic
і toc
, що підтримує Matlab. Потрібно трохи більше вишуканості.
import time
зовнішні функції обох функцій, оскільки це може зайняти досить багато часу.
tic
натиснути на нього та вийти toc
з нього.
timeit.default_timer()
краще, ніж time.time()
тому, що time.clock()
може бути більш підходящим в залежності від ОС
Зазвичай IPython - х %time
, %timeit
, %prun
і %lprun
(якщо такий line_profiler
встановлено) задовольняє мої потреби профілюючі досить добре. Однак випадок використання для tic-toc
-подібної функціональності виник, коли я намагався профілювати обчислення, які керувались інтерактивно, тобто рухом миші користувача в графічному інтерфейсі. Мені здалося, що спам- tic
і та toc
джерела в джерелах, а інтерактивне тестування - це найшвидший спосіб виявити вузькі місця. Я ходив з Timer
класом Елі Бендерського , але не був цілком задоволений, оскільки це вимагало від мене змінити відступ мого коду, що може бути незручним для деяких редакторів і заплутати систему контролю версій. Крім того, може виникнути потреба в вимірюванні часу між точками в різних функціях, які не працюватимуть зwith
заява. Спробувавши багато кмітливості Python, ось просте рішення, яке я знайшов найкращим:
from time import time
_tstart_stack = []
def tic():
_tstart_stack.append(time())
def toc(fmt="Elapsed: %s s"):
print fmt % (time() - _tstart_stack.pop())
Оскільки це працює, натискаючи на стек час початку, він буде працювати коректно для декількох рівнів tic
s і toc
s. Це також дозволяє змінювати рядок формату toc
заяви, щоб відображати додаткову інформацію, що мені сподобалось про Timer
клас Елі .
Чомусь я переймався витратами на чисту реалізацію Python, тому я протестував модуль розширення 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);
}
Це для MacOSX, і я пропустив код, щоб перевірити, чи lvl
немає меж для стислості. Хоча tictoc.res()
в моїй системі дається роздільна здатність близько 50 наносекунд, я виявив, що тремтіння вимірювання будь-якого оператора Python легко знаходиться в діапазоні мікросекунд (і набагато більше при використанні з IPython). З цього моменту видатки на реалізацію Python стають незначними, так що його можна використовувати з тією ж впевненістю, що і реалізацію C.
Я виявив, що корисність- tic-toc
Assach практично обмежена кодовими блоками, на виконання яких потрібно більше 10 мікросекунд. Нижче, timeit
для досягнення вірного вимірювання, потрібні стратегії усереднення, подібні до in .
Я щойно створив модуль [tictoc.py] для досягнення вкладених tic tocs, що і робить Matlab.
from time import time
tics = []
def tic():
tics.append(time())
def toc():
if len(tics)==0:
return None
else:
return time()-tics.pop()
І це працює так:
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()
Я сподіваюся, що це допомагає.
Погляньте на timeit
модуль. Це насправді не рівнозначно, але якщо код, який ви хочете ввести, знаходиться всередині функції, ви можете легко використовувати його.
timeit
найкраще для орієнтирів. Це навіть не повинно бути однією функцією, ви можете передавати рядно складні заяви.
pip install easy-tictoc
У коді:
from tictoc import tic, toc
tic()
#Some code
toc()
Відмова: Я автор цієї бібліотеки.
Це також можна зробити за допомогою обгортки. Дуже загальний спосіб зберігати час.
Обгортка в цьому прикладі коду завершує будь-яку функцію і друкує кількість часу, необхідного для виконання функції:
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()
Я трохи змінив відповідь @ Елі Бендерського, щоб використати __init__()
ctor та dtor, __del__()
щоб зробити час, щоб зручніше було користуватися без відступу оригінального коду:
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)
Для використання простий поставте Таймер ("блабла") на початок деякої локальної області. Пройдений час буде надруковано в кінці області:
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
Він виводить:
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
вона не видаляється після останнього дзвінка, якщо після for
циклу слідує якийсь інший код . Щоб отримати останнє значення таймера, слід видалити або перезаписати цикл timer
після for
циклу, наприклад через timer = None
.
Оновлення відповіді Елі на 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)
Як і у Eli, він може використовуватися як менеджер контексту:
import time
with Timer('Count'):
for i in range(0,10_000_000):
pass
Вихід:
[Count] Elapsed: 0.27 seconds
Я також оновив його, щоб надрукувати одиниці часу, про які повідомляється (секунд), і обрізати кількість цифр, як запропонував Can, і з можливістю також додавати до журналу файл. Ви повинні імпортувати час, щоб скористатися функцією ведення журналу:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
Спираючись на відповіді Стефана та Антонімо, я закінчився
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
в utils.py
модулі, і я використовую його з a
from utils import Tictoc
tic, toc = Tictoc()
Сюди
tic()
, toc()
і вкладати їх як в Matlabtic(1)
, toc(1)
або tic('very-important-block')
, toc('very-important-block')
і таймери з різними назвами не заважатимуть(тут toc не друкує минулий час, але повертає його.)
tic = time.time()
іtoc = time.time()
, тоді,print toc-tic, 'sec Elapsed'
як люди сказали нижче, хоч іtimeit
надійніше.