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


95

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

time.sleep(0.5)

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

time.sleep(0.05)

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

답변:


79

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

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

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

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


8
실제로 Linux 커널은 꽤 오랫동안 더 높은 틱 속도로 기본 설정되어 있으므로 "최소"절전 모드는 10ms보다 1ms에 훨씬 더 가깝습니다. 보장되지는 않습니다. 다른 시스템 활동으로 인해 CPU 경합 없이도 커널이 원하는 즉시 프로세스를 예약하지 못할 수 있습니다. 이것이 실시간 커널이 고치려고하는 것입니다. 그러나 실제로 실시간 동작이 필요하지 않는 한 높은 틱 속도 (커널 HZ 설정)를 사용하면 특별한 것을 사용하지 않고 Linux에서 보장되지는 않지만 고해상도의 절전 모드를 얻을 수 있습니다.
Glenn Maynard

1
예, 맞습니다. Linux 2.6.24-24를 사용해 보았고 거의 1000Hz 업데이트 속도를 얻을 수있었습니다. 이 작업을 할 때 Mac과 Windows에서도 코드를 실행하고 있었기 때문에 혼란 스러웠을 것입니다. 나는 Windows XP가 적어도 약 10ms의 틱 속도를 가지고 있다는 것을 알고 있습니다.
Joseph Lisee 2010-08-11

윈도우 8에 나는 단지 2ms의 아래로 내려
markmnl

2
또한 정확도는 OS에만 의존하는 것이 아니라 sleep()문서에서 더 중요한 작업을 수행하는 경우 OS가 Windows와 Linux에서 수행하는 작업에 따라 달라집니다. "일시 중지 시간은 일정으로 인해 요청한 것보다 더 길 수 있습니다. 시스템의 다른 활동 ".
markmnl 2014 년

56

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


6
Linux가 항상 요청한 것보다 약간 더 오래 잠자기를 선택한 반면 Microsoft는 반대의 접근 방식을 선택한 것은 흥미 롭습니다.
jleahy

2
@jleahy-리눅스 접근 방식이 나에게 의미가 있습니다. 수면은 실제로 일정 시간 동안 실행 우선 순위를 해제 한 후 다시 한 번 스케줄러의 의지에 따라 자신을 제출합니다 (즉시 실행을 예약하거나 실행하지 않을 수 있음) .
언더런

2
어떻게 결과를 얻었습니까? 소스 코드를 제공 할 수 있습니까? 그래프는 시간과 수면을 측정하기 위해 다른 타이머를 사용하는 인공물처럼 보입니다 (원칙적으로 타이머 간의 드리프트를 임의의 소스로 사용할 수도 있습니다 ).
jfs

2
@JF Sebastian-내가 사용한 함수는 socsci.ru.nl/wilberth/computer/sleepAccuracy.html에 있습니다. 세 번째 그래프는 보이는 것과 유사한 효과를 보여 주지만 1 ‰에 불과합니다.
Wilbert

1
@JF 세바스찬 나는 창문에 time.clock ()를 사용
Wilbert

26

로부터 문서 :

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

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

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


1
누구든지 "잡힌 신호가 해당 신호의 잡기 루틴 실행 후 sleep ()을 종료하기 때문에"를 설명 할 수 있습니까? 어떤 신호를 의미합니까? 감사!
Diego Herranz 2013 년

1
시그널은 OS가 관리하는 알림 ( en.wikipedia.org/wiki/Unix_signal ) 과 같으며, OS 가 시그널을 포착하면 해당 시그널을 처리 한 후 sleep ()이 종료됨을 의미합니다.
ArianJM

24

다음은 Wilbert의 대답에 대한 내 후속 조치입니다. 아직 많이 언급되지 않았기 때문에 Mac OS X Yosemite도 마찬가지입니다.Mac OS X Yosemite의 잠자기 동작

요청한 시간의 약 1.25 배, 때로는 요청한 시간의 1 배에서 1.25 배 사이의 수면 시간이 많은 것 같습니다. 요청한 시간의 1.25 배 이상 잠들지 않습니다 (1000 개 샘플 중 두 배).

또한 (명시 적으로 표시되지 않음) 1.25 관계는 약 0.2ms 이하로 내려갈 때까지 꽤 잘 유지되는 것 같습니다. 또한 실제 시간은 요청한 시간이 20ms 이상이되면 요청한 것보다 약 5ms 더 길어집니다.

다시 말하지만, sleep()OS X에서 Windows 또는 Linux 커널 Wilbert가 사용하던 것과는 완전히 다른 구현으로 보입니다 .


벤치 마크의 소스 코드를 github / bitbucket에 업로드 할 수 있습니까?
jfs


잠자기 자체가 정확하다고 생각하지만 Mac OS X 스케줄링은 CPU를 충분히 빠르게 제공하여 잠자기에서 깨어나는 것이 지연 될만큼 정확하지 않습니다. 정확한 기상 시간이 중요하다면 수면은 실제로 요청한 시간의 0.75 배로 설정하고 기상 후 시간을 확인하고 정확한 시간까지 점점 더 적게 수면을 반복해야하는 것 같습니다.
Mikko Rantalainen

16

왜 알아 내지 않습니까?

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

기록을 위해 HTPC에서 약 0.1ms 오류가 발생하고 랩톱에서 2ms가 발생합니다.


10
경험적 테스트는 매우 좁은 시야를 제공합니다. 이에 영향을 미치는 많은 커널, 운영 체제 및 커널 구성이 있습니다. 이전 Linux 커널은 기본적으로 더 낮은 틱 속도로 설정되어 더 세분화됩니다. Unix 구현에서는 절전 중 외부 신호가 언제든지이를 취소하고 다른 구현에서도 유사한 중단이 발생할 수 있습니다.
Glenn Maynard

6
물론 경험적 관찰은 양도 할 수 없습니다. 운영 체제 및 커널 외에도 이에 영향을 미치는 일시적인 문제가 많이 있습니다. 하드 실시간 보증이 필요한 경우 하드웨어에서 전체 시스템 설계를 고려해야합니다. 10ms가 최소 정확도라는 진술을 고려하여 관련 결과를 찾았습니다. 나는 Windows 세계에서 집에 있지 않지만 대부분의 Linux 배포판은 한동안 틱리스 커널을 실행했습니다. 이제 멀티 코어가 널리 사용되면서 시간 제한에 거의 근접하게 예약 될 가능성이 높습니다.
Ants Aasma

4

작은 수정, 몇몇 사람들은 신호에 의해 수면이 일찍 끝날 수 있다고 언급합니다. 에서 3.6 문서 는 말한다,

버전 3.5에서 변경 : 이제 신호 처리기가 예외를 발생시키는 경우를 제외하고 신호에 의해 절전 모드가 중단 된 경우에도 함수가 최소 초 이상 절전 모드로 전환됩니다 ( 이유는 PEP 475 참조 ).


3

당신이 말한 한 최소한 수면에 최선을 다할 것이라는 점을 제외하고는 sleep ()에 대해 어떤 것도 보장 할 수 없습니다 (신호는 시간이되기 전에 수면을 죽일 수 있으며 더 많은 것들이 그것을 실행시킬 수 있습니다 긴).

표준 데스크톱 운영 체제에서 얻을 수있는 최소값은 약 16ms (타이머 세분성 + 컨텍스트 전환 시간)가 될 것이지만, 시도 할 때 제공된 인수의 % 편차가 중요 할 가능성이 있습니다. 10 초 동안 잠자기 위해.

시그널, GIL을 보유한 다른 스레드, 커널 스케줄링 재미, 프로세서 속도 스테핑 등은 스레드 / 프로세스가 실제로 휴면하는 기간에 혼란을 일으킬 수 있습니다.


3
문서는 달리 말합니다.> 포착 된 신호가 해당 신호의 포착 루틴을 실행 한 후 sleep ()을 종료하기 때문에 실제 중단 시간은 요청 된 시간보다 짧을 수 있습니다.
Glenn Maynard

아 공정한 포인트, 게시물을 수정했지만 sleeps ()가 길어질 가능성이 짧은 것보다 훨씬 더 많습니다.
Nick Bastin

1
2 년 반이 지난 후에도 문서는 여전히 거짓말입니다. Windows에서 신호는 sleep ()을 종료하지 않습니다. Python 3.2, WinXP SP3에서 테스트되었습니다.
Dave

예, 그러나 KILL과 같이 수면을 선점하는 신호는 사용되지 않습니다. 문서에는 "또한 시스템의 다른 활동 일정으로 인해 일시 중단 시간이 임의의 양이 요청한 것보다 길 수 있습니다." 더 일반적입니다.
markmnl 2014 년

1
Singnals와 Windows는 어리 석습니다. Windows에서 Python time.sleep ()은 Ctrl-C와 같은 것을 캡처하기 위해 ConsoleEvent를 기다립니다.
schlenk 2014

1

더 정확하거나 더 낮은 수면 시간이 필요하다면 직접 만들어보십시오.

import time

def sleep(duration, get_now=time.perf_counter):
    now = get_now()
    end = now + duration
    while now < end:
        now = get_now()


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

sleep ()의 인수를 전달하기 위해 변수를 사용하지 마십시오. 계산을 sleep ()에 직접 삽입해야합니다.


그리고 내 터미널의 귀환

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 ───────────────────


0
def test():
    then = time.time()  # get time at the moment
    x = 0
    while time.time() <= then+1:  # stop looping after 1 second
        x += 1
        time.sleep(0.001)  # sleep for 1 ms
    print(x)

Windows 7 / Python 3.8 1000에서 수면 값을0.0005

그래서 완벽한 1ms

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