Matlab의 tic 및 toc 함수에 해당하는 Python은 무엇입니까?


112

Matlab의 tic 및 toc 함수에 해당하는 Python은 무엇입니까 ?


7
당신이 정말로 직접 해당하는 원하는 경우에, 다만 전화 tic = time.time()toc = time.time()다음, print toc-tic, 'sec Elapsed'사람들은 아래 말했듯이,하지만 timeit더 강력하다.
Joe Kington

: 나는 예를 들어 다음과 같이) timeit.default_timer (와 함께 JoeKington의 접근 @ 사용하여 더 나은 결과를 얻을 것 같다 tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer(), 다음 print toc-tic.
littleO

1
라이브러리 pytictoc은 가장 편리해 보이며 구문은 아래의 ttictoc보다 약간 더 깔끔합니다. pypi.org/project/pytictoc
FlorianH

답변:


172

timeitThiefMaster가 언급 한 것 외에도 간단한 방법은 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생각합니다. 측정하려는 항목에 따라 다릅니다.


25
@eat : 나는 정중하게 동의하지 않습니다. 사람들은 유닉스 time명령을 사용하여 프로그램의 런타임을 측정 해 왔으며이 방법은이를 Python 코드 내부에 복제합니다. 작업에 적합한 도구라면 문제가 없다고 생각합니다. timeit항상 그런 것은 아닙니다. 프로파일 러는 대부분의 요구에 대해 훨씬 더 무거운 솔루션입니다
Eli Bendersky

4
마지막 줄에 대해 제안 print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'합니다. % .2f 없이는 이해하기 어렵습니다. 좋은 아이디어에 감사드립니다.
Can Kavaklıoğlu

4
언뜻보기에는 매우 편리해 보이지만 실제로는 원하는 코드 블록을 들여 쓰기해야하므로 코드 블록의 길이와 선택한 편집기에 따라 상당히 불편할 수 있습니다. 중첩 된 사용의 경우 올바르게 작동하는 여전히 우아한 솔루션입니다.
Stefan

1
elapsed = t - time.time()대신 원하는 것 같아요 elapsed = time.time() - t. 후자의 경우 경과는 음수입니다. 이 변경 사항을 편집으로 제안했습니다.
rysqui

3
@rysqui- 현재 시간이 항상 이전 시간 보다 큰 숫자가 아닙니까? 나는 elapsed = time.time() - t그것이 항상 긍정적 인 가치를 산출하는 형태 라고 생각합니다 .
Scott Smith

32

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.\n" %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.\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...

도움이 되었기를 바랍니다.


22

tic과 toc의 가장 좋은 유사점은 단순히 파이썬으로 정의하는 것입니다.

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()

6
Matlab이 지원하는 ticand 의 중첩 된 사용의 경우 올바르게 작동하지 않습니다 toc. 좀 더 정교함이 필요합니다.
Stefan

2
기본적인 타이밍이 필요할 때 내 코드에서 유사한 기능을 구현했습니다. 그러나 import time잠재적으로 상당한 시간이 걸릴 수 있으므로 두 기능 의 외부를 제거합니다 .
Bas Swinckels 2013

이 기술을 고집하고 중첩 된 tic / toc를 처리하는 데 필요하다면 전역을 목록으로 만들고 목록으로 tic밀어 넣고 toc팝하도록하십시오.
Ahmed Fasih

1
또한 OS에 따라 더 적절할 수 있기 때문에 timeit.default_timer()더 나은 다른 곳에서 읽었습니다time.time()time.clock()
Miguel

@AhmedFasih 더 많은 것이 개선 될 수 있지만 그것이 내 대답이하는 일입니다.
antonimmo

15

일반적으로, IPython의는 %time, %timeit, %prun%lprun(한 경우 line_profiler설치) 아주 잘 내 프로파일 요구를 충족. 그러나 tic-toc대화식으로 구동되는 계산 (예 : GUI에서 사용자의 마우스 동작)을 프로파일 링하려고 할 때 유사한 기능에 대한 사용 사례 가 발생했습니다. 나는 소스에서 tics와 tocs를 스팸으로 보내면서 대화 형으로 테스트하는 것이 병목 현상을 드러내는 가장 빠른 방법이 될 것이라고 생각했습니다. 나는 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())

이것은 스택의 시작 시간을 밀어서 작동하므로 여러 수준의 tics 및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 마이크로 초 이상 걸리는 코드 블록으로 제한 된다는 사실을 발견했습니다 . 그 아래에서는 in과 같은 평균화 전략 timeit이 충실한 측정을 위해 필요합니다.


1
매우 우아합니다, @Stefan-이것이 너무 낮은 등급이라는 것을 믿을 수 없습니다. 감사!
thclark

10

tictoc에서 사용할 수 있습니다 ttictoc. 함께 설치

pip install ttictoc

다음과 같이 스크립트로 가져옵니다.

from ttictoc import tic,toc
tic()
# Some code
print(toc())

8

Matlab이하는 일인 중첩 된 tic tocs를 달성하기 위해 모듈 [tictoc.py]을 만들었습니다.

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()

도움이되기를 바랍니다.


MATLAB에서 tic / toc의 멋진 복제!
Matt

1
(AFAIK) 모듈은 싱글 톤처럼 동작하기 때문에 둘 이상의 모듈에서 동시에 사용하면 원하는대로 동작하지 않을 수 있음을 경고해야합니다.
antonimmo

3

timeit모듈을 살펴보십시오 . 실제로는 동일하지는 않지만 시간을 측정하려는 코드가 함수 내에 있으면 쉽게 사용할 수 있습니다.


예, timeit벤치 마크에 가장 적합합니다. 단일 함수일 필요도없고 매우 복잡한 문을 전달할 수 있습니다.

10
글쎄, 매우 단순한 함수 호출이 아닌 코드를 문자열로 전달하는 것은 매우 추합니다.
ThiefMaster


1

이는 래퍼를 사용하여 수행 할 수도 있습니다. 시간을 유지하는 매우 일반적인 방법.

이 예제 코드의 래퍼는 모든 함수를 래핑하고 함수를 실행하는 데 필요한 시간을 인쇄합니다.

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()

래퍼 함수 timethis를 데코레이터라고합니다. 좀 더 자세한 설명은 여기 : medium.com/pythonhive/…
Mircea

1

@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

3
이 구현의 문제 timerfor루프 뒤에 다른 코드가 있으면 마지막 호출 이후에 삭제되지 않는다는 사실 입니다. 마지막 타이머 값을 얻으려면 루프 timer이후를 삭제하거나 덮어 써야합니다 .fortimer = None
bastelflp

1
@bastelflp 방금 당신이 의미하는 바를 오해했다는 것을 깨달았습니다 ... 당신의 제안은 이제 코드에 통합되었습니다. 감사.
Shaohua Li

1

Python 3에 대한 Eli의 답변 업데이트 :

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

0

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

A의 utils.py모듈 및 나는 함께 사용

from utils import Tictoc
tic, toc = Tictoc()

이 방법

  • 당신은 단순히 사용할 수 있습니다 tic(),toc() 둥지 그들 매트랩 좋아
  • 양자 택일로, 당신은 그 이름을 수 있습니다 tic(1), toc(1)또는 tic('very-important-block'), toc('very-important-block')다른 이름을 가진 타이머는 방해하지 않을 것이다
  • 이런 식으로 가져 오면 사용하는 모듈 간의 간섭을 방지 할 수 있습니다.

(여기서 toc는 경과 시간을 인쇄하지 않고 반환합니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.