Program Tip

파이썬의 time.sleep ()은 얼마나 정확합니까?

programtip 2020. 10. 4. 13:13
반응형

파이썬의 time.sleep ()은 얼마나 정확합니까?


다음과 같이 부동 소수점 수를 줄 수 있습니다.

time.sleep(0.5)

하지만 얼마나 정확합니까? 내가 주면

time.sleep(0.05)

정말 50ms 정도 잠을 자겠습니까?


time.sleep 함수의 정확도는 기본 OS의 절전 정확도에 따라 다릅니다. 주식 Windows와 같은 비 실시간 OS의 경우 잠자기 가능한 최소 간격은 약 10-13ms입니다. 최소 10-13ms 이상일 때 그 시간의 몇 밀리 초 내에 정확한 수면을 보았습니다.

업데이트 : 아래 인용 된 문서에서 언급했듯이, 일찍 깨어 나면 다시 수면으로 돌아가는 루프에서 수면을 취하는 것이 일반적입니다.

또한 Ubuntu를 실행중인 경우 rt 커널 패키지 (최소한 Ubuntu 10.04 LTS에서)를 설치하여 가상 실시간 커널 (RT_PREEMPT 패치 세트 포함)을 사용해 볼 수 있습니다.

편집 : 수정 비 실시간 Linux 커널은 최소 절전 간격이 1ms에서 10ms에 훨씬 가깝지만 결정적이지 않은 방식으로 다릅니다.


사람들은 운영 체제와 커널의 차이점에 대해 매우 옳지 만 우분투에서는 세분화를 보지 못하고 MS7에서는 1ms 세분화를 봅니다. 다른 틱 속도뿐만 아니라 time.sleep의 다른 구현을 제안합니다. 좀 더 자세히 살펴보면 우분투에서 1μs 세분성을 제안하지만 정확도를 측정하는 데 사용하는 time.time 함수 때문입니다.Python의 Linux 및 Windows 일반적인 time.sleep 동작


로부터 문서 :

반면에 time()의 정밀도는 sleep()유닉스에 해당하는 것보다 낫습니다. 시간은 부동 소수점 숫자로 표현되고 time()사용 가능한 가장 정확한 시간을 반환하며 (사용 gettimeofday가능한 경우 Unix 사용) sleep()0이 아닌 분수가있는 시간을 허용합니다 (Unix select가 사용됨). 가능한 경우이를 구현하기 위해).

그리고 더 구체적으로 wrt sleep():

주어진 시간 (초) 동안 실행을 일시 중지합니다. 인수는보다 정확한 수면 시간을 나타내는 부동 소수점 숫자 일 수 있습니다. 포착 된 신호는 해당 신호의 포착 루틴의 다음 실행을 종료하기 때문에 실제 중단 시간 요청 된 시간 보다 짧을 수 있습니다sleep() . 또한 시스템에서 다른 활동의 스케줄링으로 인해 일시 중단 시간 임의의 양으로 요청 된 것보다 길 수 있습니다 .


Wilbert의 대답에 대한 후속 조치는 아직 많이 언급되지 않았으므로 Mac OS X Yosemite에서도 동일합니다.Mac OS X Yosemite의 잠자기 동작

Looks like a lot of the time it sleeps about 1.25 times the time that you request and sometimes sleeps between 1 and 1.25 times the time you request. It almost never (~twice out of 1000 samples) sleeps significantly more than 1.25 times the time you request.

Also (not shown explicitly) the 1.25 relationship seems to hold pretty well until you get below about 0.2 ms, after which it starts get a little fuzzy. Additionally, the actual time seems to settle to about 5 ms longer than you request after the amount of time requested gets above 20 ms.

Again, it appears to be a completely different implementation of sleep() in OS X than in Windows or whichever Linux kernal Wilbert was using.


Why don't you find out:

from datetime import datetime
import time

def check_sleep(amount):
    start = datetime.now()
    time.sleep(amount)
    end = datetime.now()
    delta = end-start
    return delta.seconds + delta.microseconds/1000000.

error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error

For the record, I get around 0.1ms error on my HTPC and 2ms on my laptop, both linux machines.


A small correction, several people mention that sleep can be ended early by a signal. In the 3.6 docs it says,

Changed in version 3.5: The function now sleeps at least secs even if the sleep is interrupted by a signal, except if the signal handler raises an exception (see PEP 475 for the rationale).


You can't really guarantee anything about sleep(), except that it will at least make a best effort to sleep as long as you told it (signals can kill your sleep before the time is up, and lots more things can make it run long).

For sure the minimum you can get on a standard desktop operating system is going to be around 16ms (timer granularity plus time to context switch), but chances are that the % deviation from the provided argument is going to be significant when you're trying to sleep for 10s of milliseconds.

Signals, other threads holding the GIL, kernel scheduling fun, processor speed stepping, etc. can all play havoc with the duration your thread/process actually sleeps.


Tested this recently on Python 3.7 on Windows 10. Precision was around 1ms.


def start(self):
    sec_arg = 10.0
    cptr = 0
    time_start = time.time()
    time_init = time.time()
    while True:
        cptr += 1
        time_start = time.time()
        time.sleep(((time_init + (sec_arg * cptr)) - time_start ))

        # AND YOUR CODE .......
        t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
        t00.start()

Do not use a variable to pass the argument of sleep (), you must insert the calculation directly into sleep ()


And the return of my terminal

1 ───── 17:20:16.891 ───────────────────

2 ───── 17:20:18.891 ───────────────────

3 ───── 17:20:20.891 ───────────────────

4 ───── 17:20:22.891 ───────────────────

5 ───── 17 : 20 : 24.891 ───────────────────

....

689 ─── 17 : 43 : 12.891 ────────────────────

690 ─── 17 : 43 : 14.890 ────────────────────

691 ─── 17 : 43 : 16.891 ────────────────────

692 ─── 17 : 43 : 18.890 ───────────────────

693 ─── 17 : 43 : 20.891 ───────────────────

...

727 ─── 17 : 44 : 28.891 ────────────────────

728 ─── 17 : 44 : 30.891 ────────────────────

729 ─── 17 : 44 : 32.891 ────────────────────

730 ─── 17 : 44 : 34.890 ────────────────────

731 ─── 17 : 44 : 36.891 ────────────────────

참고 URL : https://stackoverflow.com/questions/1133857/how-accurate-is-pythons-time-sleep

반응형