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())เนื่องจากวิธีนี้ทำงานได้โดยการกดเวลาเริ่มต้นบนสแต็กจึงทำงานได้อย่างถูกต้องสำหรับหลายระดับของtics และtocs นอกจากนี้ยังอนุญาตให้เปลี่ยนสตริงรูปแบบของ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.28stimerจะไม่ถูกลบออกหลังจากการโทรครั้งสุดท้ายหากมีรหัสอื่น ๆ ตามหลังการ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มีประสิทธิภาพมากขึ้น