2013-03-23 1 views
7

목록에서 빠르고 정확하게 메시지를 보내야합니다. 하나의 목록은 +/- 10ms 간격으로 100ms마다 메시지를 보내야합니다. 나는 아래의 코드를 사용해 보았지만, 문제는 타이머가 100ms를 기다린 다음 모든 계산을 완료해야 타이머가 허용되는 윈도우에서 떨어지는 것이다.빠르고 정확한 Python 반복 타이머

단순히 대기 시간을 줄이면 지저분하고 신뢰할 수없는 해킹입니다. 루프 중에 목록이 편집되는 경우 메시지 루프 주위에 Lock이 있습니다.

python이 메시지를 100ms 내내 일관되게 보내는 방법에 대한 생각은 무엇입니까? 감사합니다

from threading import Timer 
from threading import Lock 

class RepeatingTimer(object): 
    def __init__(self,interval, function, *args, **kwargs): 
     super(RepeatingTimer, self).__init__() 
     self.args = args 
     self.kwargs = kwargs 
     self.function = function 
     self.interval = interval 
     self.start() 

    def start(self): 
     self.callback() 

    def stop(self): 
     self.interval = False 

    def callback(self): 
     if self.interval: 
      self.function(*self.args, **self.kwargs) 
      Timer(self.interval, self.callback,).start() 

def loop(messageList): 
    listLock.acquire() 
    for m in messageList: 
     writeFunction(m) 
    listLock.release() 


MESSAGE_LIST = [] #Imagine this is populated with the messages 
listLock = Lock() 
rt = RepeatingTimer(0.1,loop,MESSAGE_LIST) 
#Do other stuff after this 

나는 writeFunction이 약간의 지연을 일으키지 만 10ms는 넘지 않는다는 것을 이해합니다. 필자는 본질적으로 각 메시지마다 100ms마다 함수를 호출해야합니다. messagelist는 작고, 보통 요소보다 작습니다. P

+0

'10ms마다와 작업, +/- 1ms의'하나 :( –

답변

0

스토어 시작 시간 :

다음 과제는 10ms마다이 작업 +/- 1ms의를하는 것입니다. 메시지를 보냅니다. 끝 시간 가져와. timeTaken = end-start를 계산하십시오. FP 초로 변환하십시오. 수면 (0.1 시간 경과). 루프백.

8

예, 간단한 대기는 지저분하고 더 좋은 대안이 있습니다.

먼저, 고정밀 타이머가 필요합니다. 몇 가지 대안이 있으며 OS에 따라 the most accurate one을 선택할 수도 있습니다.

두 번째로 basics preemptive multitasking을 알고 있어야하며 고정밀 도로 sleep 기능이없고 실제 해상도가 OS와 다를 것임을 이해해야합니다. 예를 들어, 우리가 Windows를 말하면, the minimal sleep interval might be around 10-13 ms.

세 번째로, 매우 정확한 시간 간격 (고해상도 타이머가 있다고 가정)을 항상 기다릴 수는 있지만 CPU로드가 높다는 절충점이 있음을 기억하십시오. 이 기술을 busy waiting이라고합니다.

while(True): 
    if time.clock() == something: 
     break 

따라서 실제 솔루션은 하이브리드 타이머를 만드는 것입니다. 정기적 인 sleep 함수를 사용하여주기의 대부분을 기다린 다음 sleep(0) 트릭을하면서 루프의 고정밀 타이머를 프로빙하기 시작합니다. Sleep(0) (플랫폼에 따라 다름)은 가능한 최소 시간 동안 대기하고 남은 시간 조각을 나머지 프로세스로 릴리스하고 CPU 컨텍스트를 전환합니다. 다음은 관련 discussion입니다.

아이디어는 Ryan Geiss의 Timing in Win32 문서에 자세히 설명되어 있습니다. C 및 Windows API 용이지만 기본 원칙도 여기에 적용됩니다.

+2

행운이 안전 time.clock을()> = 뭔가 내가 생각 확인하지 않는 것입니다 "time.clock()"이 "무언가"를 약간 뛰어 넘을 위험이 있음 – vac

+0

멋진 'busy waiting'레이블에 속지 마십시오 ;-). 가능한 한 피해야합니다. – jjmontes

0

이 시도 :

#!/usr/bin/python 
import time; # This is required to include time module. 
from threading import Timer 

def hello(start, interval, count): 
    ticks = time.time() 
    t = Timer(interval - (ticks-start-count*interval), hello, [start, interval, count+1]) 
    t.start() 
    print "Number of ticks since 12:00am, January 1, 1970:", ticks, " #", count 

dt = 1.25 # interval in sec 
t = Timer(dt, hello, [round(time.time()), dt, 0]) # start over at full second, round only for testing here 
t.start()