在没有busywait的情况下在python中实现亚毫秒处理

前端之家收集整理的这篇文章主要介绍了在没有busywait的情况下在python中实现亚毫秒处理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我将如何使用linux下的python(在单核Raspberry Pi上运行)实现毫秒精度的数组处理.

我正在尝试解析MIDI文件中的信息,该文件已被预处理到一个数组,其中每毫秒我检查数组是否在当前时间戳处有条目并触发某些功能(如果有).

目前我正在使用time.time()并使用繁忙的等待(如here结束).这会占用所有cpu,因此我选择了更好的解决方案.

@H_502_9@# iterate through all milliseconds for current_ms in xrange(0,last+1): start = time() # check if events are to be processed try: events = allEvents[current_ms] # iterate over all events for this millisecond for event in events: # check if event contains note information if 'note' in event: # check if mapping to pin exists if event['note'] in mapping: pin = mapping[event['note']] # check if event contains on/off information if 'mode' in event: if event['mode'] == 0: pin_off(pin) elif event['mode'] == 1: pin_on(pin) else: debug("unknown mode in event:"+event) else: debug("no mapping for note:" + event['note']) except: pass end = time() # fill the rest of the millisecond while (end-start) < (1.0/(1000.0)): end = time()

last是最后一个事件的毫秒(从预处理中得知)

这不是关于time() vs clock()更多关于sleep vs busy wait的问题.

由于too low accuracy of sleep(),我无法真正睡在“毫秒剩余”循环中.如果我要使用ctypes,我将如何正确地进行操作?

是否有一些Timer库可以每毫秒可靠地调用一次回调?

我目前的实现是在GitHub.使用这种方法我在drum_sample上得到大约4或5ms的偏差,总共3.7s(有模拟,因此没有附加真正的硬件).在30.7s样本上,偏差约为32ms(因此它至少不是线性的!).

我已尝试使用以下代码使用time.sleep()nanosleep() via ctypes

@H_502_9@import time import timeit import ctypes libc = ctypes.CDLL('libc.so.6') class Timespec(ctypes.Structure): """ timespec struct for nanosleep,see: http://linux.die.net/man/2/nanosleep """ _fields_ = [('tv_sec',ctypes.c_long),('tv_nsec',ctypes.c_long)] libc.nanosleep.argtypes = [ctypes.POINTER(Timespec),ctypes.POINTER(Timespec)] nanosleep_req = Timespec() nanosleep_rem = Timespec() def nsleep(us): #print('nsleep: {0:.9f}'.format(us)) """ Delay microseconds with libc nanosleep() using ctypes. """ if (us >= 1000000): sec = us/1000000 us %= 1000000 else: sec = 0 nanosleep_req.tv_sec = sec nanosleep_req.tv_nsec = int(us * 1000) libc.nanosleep(nanosleep_req,nanosleep_rem) LOOPS = 10000 def do_sleep(min_sleep): #print('try: {0:.9f}'.format(min_sleep)) total = 0.0 for i in xrange(0,LOOPS): start = timeit.default_timer() nsleep(min_sleep*1000*1000) #time.sleep(min_sleep) end = timeit.default_timer() total += end - start return (total / LOOPS) iterations = 5 iteration = 1 min_sleep = 0.001 result = None while True: result = do_sleep(min_sleep) #print('res: {0:.9f}'.format(result)) if result > 1.5 * min_sleep: if iteration > iterations: break else: min_sleep = result iteration += 1 else: min_sleep /= 2.0 print('FIN: {0:.9f}'.format(result))

我的i5的结果是

FIN: 0.000165443

而在RPi上它是

FIN: 0.000578617

这表明睡眠时间约为0.1或0.5毫秒,给定的抖动(倾向于睡得更久)最多可以帮助我减少负荷.

最佳答案
一种可能的解决方案,使用sched模块:

@H_502_9@import sched import time def f(t0): print 'Time elapsed since t0:',time.time() - t0 s = sched.scheduler(time.time,time.sleep) for i in range(10): s.enterabs(t0 + 10 + i,f,(t0,)) s.run()

结果:

@H_502_9@Time elapsed since t0: 10.0058200359 Time elapsed since t0: 11.0022959709 Time elapsed since t0: 12.0017120838 Time elapsed since t0: 13.0022599697 Time elapsed since t0: 14.0022521019 Time elapsed since t0: 15.0015859604 Time elapsed since t0: 16.0023040771 Time elapsed since t0: 17.0023028851 Time elapsed since t0: 18.0023078918 Time elapsed since t0: 19.002286911

除了大约2毫秒的恒定偏移(你可以校准)之外,抖动似乎在1或2毫秒的数量级上(由time.time本身报告).不确定这是否足以满足您的应用需求.

如果您在此期间需要做一些有用的工作,您应该研究多线程或多处理.

注意:在RPi上运行的标准Linux发行版不是硬实时操作系统. Python也可以显示非确定性时序,例如什么时候开始垃圾收集.因此,您的代码可能在大多数情况下以低抖动运行,但您可能偶尔会遇到“hickups”,这会有一些延迟.

猜你在找的Python相关文章