Python tương đương với các hàm tic và toc của Matlab là gì?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
sau đó print toc-tic
.
Python tương đương với các hàm tic và toc của Matlab là gì?
tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
sau đó print toc-tic
.
Câu trả lời:
Ngoài timeit
những gì ThiefMaster đã đề cập, một cách đơn giản để làm điều đó chỉ là (sau khi nhập time
):
t = time.time()
# do stuff
elapsed = time.time() - t
Tôi có một lớp trợ giúp mà tôi muốn sử dụng:
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))
Nó có thể được sử dụng như một trình quản lý ngữ cảnh:
with Timer('foo_stuff'):
# do some foo
# do some stuff
Đôi khi tôi thấy kỹ thuật này thuận tiện hơn timeit
- tất cả phụ thuộc vào những gì bạn muốn đo.
time
lệnh unix để đo thời gian chạy của các chương trình và phương pháp này sao chép điều này bên trong mã Python. Tôi thấy nó không có gì sai, miễn là nó là công cụ phù hợp với công việc. timeit
không phải lúc nào đó, và một hồ sơ là một giải pháp nhiều nặng hơn đối với hầu hết nhu cầu
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Thật khó hiểu nếu không có% .2f. Cảm ơn vì ý tưởng tuyệt vời.
elapsed = t - time.time()
, thay vì elapsed = time.time() - t
. Trong phần sau trôi qua sẽ là tiêu cực. Tôi đã đề xuất thay đổi này như một chỉnh sửa.
elapsed = time.time() - t
là biểu mẫu luôn mang lại giá trị dương.
Tôi có cùng một câu hỏi khi chuyển sang python từ Matlab. Với sự trợ giúp của chủ đề này, tôi đã có thể xây dựng một tương tự chính xác của Matlab tic()
và các toc()
hàm. Chỉ cần chèn mã sau vào đầu tập lệnh của bạn.
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)
Đó là nó! Bây giờ chúng tôi đã sẵn sàng để sử dụng đầy đủ tic()
và toc()
giống như trong Matlab. Ví dụ
tic()
time.sleep(5)
toc() # returns "Elapsed time: 5.00 seconds."
Trên thực tế, điều này linh hoạt hơn các chức năng Matlab tích hợp sẵn. Tại đây, bạn có thể tạo một phiên bản khác của biểu tượng TicTocGenerator
để theo dõi nhiều hoạt động hoặc chỉ để tính giờ mọi thứ theo cách khác. Ví dụ, trong khi định thời gian cho một tập lệnh, giờ đây chúng ta có thể định thời gian cho từng đoạn của tập lệnh một cách riêng biệt, cũng như toàn bộ tập lệnh. (Tôi sẽ cung cấp một ví dụ cụ thể)
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)
Bây giờ bạn sẽ có thể tính thời gian cho hai việc riêng biệt: Trong ví dụ sau, chúng tôi tính thời gian cho tổng tập lệnh và các phần của tập lệnh một cách riêng biệt.
tic()
time.sleep(5)
tic2()
time.sleep(3)
toc2() # returns "Elapsed time 2: 5.00 seconds."
toc() # returns "Elapsed time: 8.00 seconds."
Trên thực tế, bạn thậm chí không cần phải sử dụng tic()
mỗi lần. Nếu bạn có một loạt lệnh mà bạn muốn bấm giờ, thì bạn có thể viết
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...
Tôi hy vọng rằng điều này là hữu ích.
Tương tự tốt nhất tuyệt đối của tic và toc sẽ chỉ đơn giản là xác định chúng trong 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"
Sau đó, bạn có thể sử dụng chúng như:
tic()
# do stuff
toc()
tic
và toc
, mà Matlab hỗ trợ. Một chút tinh tế sẽ được yêu cầu.
import time
bên ngoài của cả hai chức năng, vì nó có thể mất một khoảng thời gian.
tic
đẩy nó đến và toc
bật ra khỏi nó.
timeit.default_timer()
là tốt hơn so với time.time()
vì time.clock()
có thể thích hợp hơn tùy thuộc vào hệ điều hành
Thông thường, IPython của %time
, %timeit
, %prun
và %lprun
(nếu ai đã line_profiler
cài đặt) đáp ứng nhu cầu profiling của tôi khá tốt. Tuy nhiên, một trường hợp sử dụng cho tic-toc
chức năng giống đã nảy sinh khi tôi cố gắng lập hồ sơ các phép tính được điều khiển tương tác, tức là bằng chuyển động chuột của người dùng trong GUI. Tôi cảm thấy như gửi thư rác tic
s và toc
s trong các nguồn trong khi thử nghiệm tương tác sẽ là cách nhanh nhất để tiết lộ tắc nghẽn. Tôi đã tham gia Timer
lớp học của Eli Bendersky , nhưng không hoàn toàn hài lòng, vì nó yêu cầu tôi thay đổi thụt đầu dòng trong mã của mình, điều này có thể gây bất tiện trong một số trình chỉnh sửa và gây nhầm lẫn cho hệ thống kiểm soát phiên bản. Hơn nữa, có thể cần phải đo thời gian giữa các điểm trong các chức năng khác nhau, điều này sẽ không hoạt động vớiwith
tuyên bố. Sau khi thử rất nhiều sự thông minh của Python, đây là giải pháp đơn giản mà tôi thấy hiệu quả nhất:
from time import time
_tstart_stack = []
def tic():
_tstart_stack.append(time())
def toc(fmt="Elapsed: %s s"):
print fmt % (time() - _tstart_stack.pop())
Vì điều này hoạt động bằng cách đẩy thời gian bắt đầu vào một ngăn xếp, nó sẽ hoạt động chính xác cho nhiều cấp độ tic
s và toc
s. Nó cũng cho phép một người thay đổi chuỗi định dạng của toc
câu lệnh để hiển thị thông tin bổ sung, mà tôi thích về Timer
lớp của Eli .
Vì một số lý do, tôi quan tâm đến chi phí triển khai Python thuần túy, vì vậy tôi cũng đã thử nghiệm một mô-đun mở rộng 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);
}
Đây là dành cho MacOSX và tôi đã bỏ qua mã để kiểm tra xem có lvl
nằm ngoài giới hạn hay không cho ngắn gọn. Trong khi tictoc.res()
mang lại độ phân giải khoảng 50 nano giây trên hệ thống của tôi, tôi nhận thấy rằng độ rung khi đo bất kỳ câu lệnh Python nào dễ dàng nằm trong phạm vi micro giây (và nhiều hơn nữa khi được sử dụng từ IPython). Tại thời điểm này, chi phí triển khai Python trở nên không đáng kể, vì vậy nó có thể được sử dụng với độ tin cậy tương tự như việc triển khai C.
Tôi nhận thấy rằng tính hữu ích của tic-toc
-approach thực tế bị giới hạn ở các khối mã mất hơn 10 micro giây để thực thi. Dưới đó, các chiến lược tính trung bình như trong timeit
được yêu cầu để có được một phép đo trung thực.
Bạn có thể sử dụng tic
và toc
từ ttictoc
. Cài đặt nó với
pip install ttictoc
Và chỉ cần nhập chúng vào tập lệnh của bạn như sau
from ttictoc import tic,toc
tic()
# Some code
print(toc())
Tôi vừa tạo một mô-đun [tictoc.py] để đạt được các tocs tic lồng nhau, đó là những gì Matlab làm.
from time import time
tics = []
def tic():
tics.append(time())
def toc():
if len(tics)==0:
return None
else:
return time()-tics.pop()
Và nó hoạt động theo cách này:
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()
Tôi hy vọng nó sẽ giúp.
Hãy xem các timeit
mô-đun. Nó không thực sự tương đương nhưng nếu mã bạn muốn đếm thời gian nằm trong một hàm, bạn có thể dễ dàng sử dụng nó.
timeit
là tốt nhất cho điểm chuẩn. Nó thậm chí không cần phải là một hàm duy nhất, bạn có thể chuyển các câu lệnh phức tạp.
pip install easy-tictoc
Trong mã:
from tictoc import tic, toc
tic()
#Some code
toc()
Tuyên bố từ chối trách nhiệm: Tôi là tác giả của thư viện này.
Điều này cũng có thể được thực hiện bằng cách sử dụng một trình bao bọc. Cách giữ thời gian rất chung chung.
Trình bao bọc trong mã ví dụ này bao bọc bất kỳ hàm nào và in ra khoảng thời gian cần thiết để thực thi hàm:
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()
Tôi đã thay đổi câu trả lời của @Eli Bendersky một chút để sử dụng ctor __init__()
và dtor __del__()
để định thời gian, để có thể sử dụng nó thuận tiện hơn mà không cần thụt lề mã gốc:
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)
Để sử dụng, đơn giản đặt Timer ("blahblah") ở đầu một số phạm vi cục bộ. Thời gian đã trôi qua sẽ được in ở cuối phạm vi:
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
Nó in ra:
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
không bị xóa sau lần gọi cuối cùng, nếu bất kỳ mã nào khác theo sau for
vòng lặp. Để nhận giá trị bộ đếm thời gian cuối cùng, người ta nên xóa hoặc ghi đè lên timer
sau for
vòng lặp, ví dụ qua timer = None
.
Cập nhật câu trả lời của Eli cho 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)
Cũng giống như của Eli, nó có thể được sử dụng như một trình quản lý ngữ cảnh:
import time
with Timer('Count'):
for i in range(0,10_000_000):
pass
Đầu ra:
[Count] Elapsed: 0.27 seconds
Tôi cũng đã cập nhật nó để in đơn vị thời gian được báo cáo (giây) và cắt bớt số chữ số theo đề xuất của Can, và với tùy chọn thêm vào tệp nhật ký. Bạn phải nhập ngày giờ để sử dụng tính năng ghi nhật ký:
import time
import datetime
with Timer('Count', 'log.txt'):
for i in range(0,10_000_000):
pass
Dựa trên câu trả lời của Stefan và antonimmo, tôi đã kết thúc
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
trong một utils.py
mô-đun và tôi sử dụng nó với
from utils import Tictoc
tic, toc = Tictoc()
Cách này
tic()
, toc()
và làm tổ họ thích trong Matlabtic(1)
, toc(1)
hay tic('very-important-block')
, toc('very-important-block')
và giờ với tên gọi khác nhau sẽ không can thiệp(ở đây toc không in thời gian đã trôi qua mà trả về nó.)
tic = time.time()
vàtoc = time.time()
, sau đóprint toc-tic, 'sec Elapsed'
Như mọi người đã nói bên dưới,timeit
mạnh mẽ hơn.