2024-06-16 10:25:09 发布
网友
我正在建立一个基于树莓皮的设备。它将有几个并发函数,这些函数应该同时工作。在这种情况下,使用AsiCIO看起来是一个合理的选择(我可以用C++编写C++中的所有这些东西,但是Python代码看起来更紧凑)
其中一个功能是通过GPIO脉冲驱动步进电机。这些脉冲应为5-10微秒长。有没有一种方法可以在亚毫秒的时间间隔内使用异步睡眠来进入睡眠状态?在
Is there a way to get asleep for a sub-milliseconds intervals with asyncio sleep?
在Linux上,asyncio使用epoll_wait系统调用,该调用以毫秒为单位指定超时,因此任何次毫秒都不起作用,尽管可以在asyncio.sleep()中指定它。在
epoll_wait
asyncio.sleep()
您可以通过运行以下程序在计算机上进行测试:
import asyncio, os SLEEP_DURATION = 5e-3 # 5 ms sleep async def main(): while True: # suspend execution await asyncio.sleep(SLEEP_DURATION) # execute a syscall visible in strace output os.stat('/tmp') asyncio.run(main())
将程序保存为sleep1.py,并在strace下运行,如下所示:
sleep1.py
strace
trc文件将包含相当精确的幕后活动时间安排。在Python启动序列之后,程序基本上在无限循环中执行以下操作:
trc
24015 getpid() = 24015 <0.000010> 24015 epoll_wait(3, [], 1, 5) = 0 <0.005071> 24015 epoll_wait(3, [], 1, 0) = 0 <0.000010> 24015 stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=45056, ...}) = 0 <0.000014>
我们看到对getpid()的调用,对epoll_wait的两次调用,最后是对{}的调用。第一个epoll_wait实际上是相关的,它以毫秒为单位指定超时,并在大约所需的时间段内休眠。如果我们将睡眠持续时间降低到亚毫秒,例如100e-6,strace表明asyncio仍然从epoll_wait请求一个1ms超时,并得到相同的超时值。同样的情况也发生在15秒的超时。如果指定14 us或更小的超时,asyncio实际上请求无超时轮询,epoll_wait在8us内完成。然而,第二个epoll_wait也需要8个us,所以你不能指望任何形状的微秒分辨率。在
getpid()
即使您使用线程和繁忙的循环,您也可能会遇到GIL的同步问题。这可能是用C++或RISE等低级语言完成的,即使如此,你也需要对OS调度器小心谨慎。在
在Linux上,asyncio使用
epoll_wait
系统调用,该调用以毫秒为单位指定超时,因此任何次毫秒都不起作用,尽管可以在asyncio.sleep()
中指定它。在您可以通过运行以下程序在计算机上进行测试:
将程序保存为
^{pr2}$sleep1.py
,并在strace
下运行,如下所示:trc
文件将包含相当精确的幕后活动时间安排。在Python启动序列之后,程序基本上在无限循环中执行以下操作:我们看到对}的调用。第一个
getpid()
的调用,对epoll_wait
的两次调用,最后是对{epoll_wait
实际上是相关的,它以毫秒为单位指定超时,并在大约所需的时间段内休眠。如果我们将睡眠持续时间降低到亚毫秒,例如100e-6,strace
表明asyncio仍然从epoll_wait
请求一个1ms超时,并得到相同的超时值。同样的情况也发生在15秒的超时。如果指定14 us或更小的超时,asyncio实际上请求无超时轮询,epoll_wait
在8us内完成。然而,第二个epoll_wait
也需要8个us,所以你不能指望任何形状的微秒分辨率。在即使您使用线程和繁忙的循环,您也可能会遇到GIL的同步问题。这可能是用C++或RISE等低级语言完成的,即使如此,你也需要对OS调度器小心谨慎。在
相关问题 更多 >
编程相关推荐