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
คำสั่งunix เพื่อวัดเวลาทำงานของโปรแกรมมาโดยตลอดและวิธีนี้จะจำลองสิ่งนี้ภายในรหัส Python ฉันไม่เห็นอะไรผิดปกติตราบใดที่มันเป็นเครื่องมือที่เหมาะสมสำหรับงาน timeit
ไม่ได้เป็นเช่นนั้นเสมอไปและผู้สร้างโปรไฟล์เป็นโซลูชันที่มีน้ำหนักมากสำหรับความต้องการส่วนใหญ่
print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
สำหรับบรรทัดสุดท้ายที่ผมจะแนะนำ มันยากที่จะเข้าใจหากไม่มี% .2f ขอบคุณสำหรับความคิดที่ดี
elapsed = t - time.time()
elapsed = time.time() - t
ในช่วงหลังที่ผ่านไปจะเป็นลบ ฉันแนะนำการเปลี่ยนแปลงนี้เป็นการแก้ไข
elapsed = time.time() - t
เป็นรูปแบบที่ให้ค่าเป็นบวกเสมอ
ฉันมีคำถามเดียวกันเมื่อฉันย้ายไป python จาก Matlab ด้วยความช่วยเหลือของเธรดนี้ฉันสามารถสร้างอะนาล็อกที่แน่นอนของ 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
ฟังก์ชัน -like เกิดขึ้นเมื่อฉันพยายามสร้างโปรไฟล์การคำนวณที่ขับเคลื่อนแบบโต้ตอบกล่าวคือโดยการเคลื่อนไหวเมาส์ของผู้ใช้ใน GUI ฉันรู้สึกเหมือนสแปมtic
และtoc
ในแหล่งที่มาโต้ตอบขณะที่การทดสอบจะเป็นวิธีที่เร็วที่สุดที่จะเผยให้เห็นคอขวด ฉันไปกับTimer
ชั้นเรียนของ Eli Bendersky แต่ไม่มีความสุขอย่างเต็มที่เนื่องจากต้องเปลี่ยนการเยื้องรหัสของฉันซึ่งอาจไม่สะดวกในผู้แก้ไขบางคนและทำให้ระบบควบคุมเวอร์ชันสับสน ยิ่งไปกว่านั้นอาจจำเป็นต้องวัดเวลาระหว่างจุดต่างๆในฟังก์ชั่นต่างๆซึ่งจะใช้ไม่ได้กับไฟล์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
คลาสของ Eli
ด้วยเหตุผลบางอย่างฉันกังวลกับค่าใช้จ่ายของการใช้งาน 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
-approach นั้น จำกัด อยู่ที่บล็อกโค้ดที่ใช้เวลามากกว่า 10 ไมโครวินาทีในการดำเนินการ ด้านล่างนี้timeit
จำเป็นต้องมีกลยุทธ์การหาค่าเฉลี่ยเช่น in เพื่อให้ได้การวัดที่น่าเชื่อถือ
คุณสามารถใช้tic
และจากtoc
ttictoc
ติดตั้งด้วย
pip install ttictoc
และนำเข้าในสคริปต์ของคุณดังต่อไปนี้
from ttictoc import tic,toc
tic()
# Some code
print(toc())
ฉันเพิ่งสร้างโมดูล [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()
ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนห้องสมุดนี้
สามารถทำได้โดยใช้กระดาษห่อหุ้ม วิธีการรักษาเวลาโดยทั่วไป
Wrapper ในโค้ดตัวอย่างนี้จะปิดฟังก์ชันใด ๆ และพิมพ์ระยะเวลาที่จำเป็นในการเรียกใช้ฟังก์ชัน:
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()
ฉันเปลี่ยนคำตอบของ @Eli Bendersky เล็กน้อยเพื่อใช้ ctor __init__()
และ 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)
ในการใช้งานให้ใส่ Timer ("blahblah") ที่จุดเริ่มต้นของขอบเขตท้องถิ่น เวลาที่ผ่านไปจะถูกพิมพ์ที่ส่วนท้ายของขอบเขต:
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
การอัปเดตคำตอบของ Eliสำหรับ 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
จากคำตอบของ 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()
และรังพวกเขาต้องการใน 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
มีประสิทธิภาพมากขึ้น