python - 异步: sleep for sub-millisecond interval

标签 python python-asyncio

我正在构建一个基于树莓派的设备。它将具有多个应同时工作的并发功能。在这种情况下,使用 asyncio 看起来是一个合理的选择(好吧,我可以用线程用 C++ 编写所有这些东西,但 python 代码看起来更紧凑)

其中一个功能是通过 GPIO 脉冲驱动步进电机。这些脉冲的长度应为 5-10 微秒。有没有办法通过异步 sleep 以亚毫秒的间隔进入休眠状态?

最佳答案

Is there a way to get asleep for a sub-milliseconds intervals with asyncio sleep?

在 Linux 上,asyncio 使用 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 下运行它,如下所示:

$ strace -fo trc -T python3.7 sleep1.py
<wait a second or two, then press Ctrl-C to interrupt>

trc 文件将包含幕后发生的事情的相当精确的时间。在Python启动序列之后,程序基本上在无限循环中执行以下操作:

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 的调用,最后是对 stat 的调用。第一个 epoll_wait 实际上是相关的,它指定超时(以毫秒为单位),并休眠大约所需的时间。如果我们将 sleep 持续时间降低到亚毫秒,例如100e-6,strace 显示 asyncio 仍然从 epoll_wait 请求 1ms 超时,并获得同样多的超时。当超时时间降至 15 us 时,也会发生同样的情况。如果您指定 14 us 或更小的超时,asyncio 实际上会请求无超时轮询,并且 epoll_wait 在 8 us 内完成。但是,第二个 epoll_wait 也需要 8 us,因此您不能真正指望任何形式的微秒分辨率。

即使您使用线程和忙循环,您也可能会遇到 GIL 同步问题。这可能应该用 C++ 或 Rust 等较低级语言来完成,即使如此,您也需要小心操作系统调度程序。

关于python - 异步: sleep for sub-millisecond interval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54497181/

相关文章:

python - cv2、scipy.misc 和 skimage 之间的区别

python - 使用队列的 Asyncio 持久客户端协议(protocol)类

python - 我可以使用 python 开发 Google Chrome 扩展程序吗?

python - 异步 : RuntimeError this event loop is already running

python - "RuntimeError: This event loop is already running";在python 3.6.5中调试aiohttp,asyncio和IDE "spyder3"

python-asyncio - 运行时错误: Event loop is closed after main coroutine is completed

python - 将异步任务发送到在其他线程中循环运行

python - 如果另一个文件中存在单词,则从文件中删除单词

python - Django:获取 TabularInline 模型对象

python - Scipy Optimize 仅返回 x0,仅完成一次迭代