什么是Matlab的tic和toc函数的Python等价物?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是Matlab的tic和toc函数的Python等价物?相关的知识,希望对你有一定的参考价值。
什么是Matlab的tic and toc functions的Python等价物?
除了ThiefMaster提到的timeit
之外,一个简单的方法就是(在导入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
更方便 - 这一切都取决于你想要测量的东西。
将Eli's answer更新为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建议的位数,并且还可以附加到日志文件中。您必须导入datetime才能使用日志记录功能:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
在Stefan和antonimmo的答案的基础上,我结束了
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
模块中,我使用它
from utils import Tictoc
tic, toc = Tictoc()
这条路
- 你可以简单地使用
tic()
,toc()
并在Matlab中嵌套它们 - 或者,您可以命名它们:
tic(1)
,toc(1)
或tic('very-important-block')
,toc('very-important-block')
和具有不同名称的计时器不会干扰 - 以这种方式导入它们可防止使用它的模块之间的干
(此处toc不会打印已用时间,但会返回它。)
当我从Matlab迁移到python时,我遇到了同样的问题。在这个线程的帮助下,我能够构建一个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.
" %tempTimeInterval )
def tic():
# Records a time in TicToc, marks the beginning of a time interval
toc(False)
而已!现在我们已经准备好像在Matlab中一样充分利用tic()
和toc()
。例如
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.
" %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()
通常,IPython的%time
,%timeit
,%prun
和%lprun
(如果安装了line_profiler
)可以很好地满足我的分析需求。然而,当我试图剖析交互式驱动的计算时,即用户在GUI中的鼠标移动时,出现了类似tic-toc
功能的用例。我觉得在源代码中发送tic
s和toc
s是垃圾邮件,而交互式测试则是揭示瓶颈的最快方法。我选择了Eli Bendersky的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
语句的格式字符串以显示其他信息,我喜欢Eli的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
方法的实用性实际上仅限于执行时间超过10微秒的代码块。在此之下,需要像timeit
这样的平均策略来获得忠实的测量。
以防有人感兴趣。基于所有其他答案,我写了一个tictoc类,其中最好的一切。
github上的链接是here.
你也可以使用pip来获取它。
pip install ttictoc
至于如何使用它:
导入它
from ttictoc import TicToc
使用'with'语句
无需创建任何对象,您可以按照以下步骤计算代码。
with TicToc('name'):
some code...
# Prints the elaps以上是关于什么是Matlab的tic和toc函数的Python等价物?的主要内容,如果未能解决你的问题,请参考以下文章