高效快速的Python While循环在使用sleep()时

35
我正在尝试使用Pyserial通过串口与设备通信。由于需要不断发送命令,因此必须将它们放置在Python的while循环中。
我目前正在使用这段代码,并查看了python process takes 100% CPU:
while True:
    #do some serial sending here
    time.sleep(0.2)

这段代码可以正常工作。但发送速度较慢。我试图通过减少 sleep 的间隔来加快速度,但它似乎会过多地占用 CPU 资源。
简而言之,有没有一种有效的方法可以在保持低 CPU 资源消耗的同时无限循环迭代 while 循环?

根据这篇帖子,time.sleep的开销非常小,你可能需要检查你的代码中串行发送部分。 - xvatar
1
你试过睡眠0.00001吗?这似乎很荒谬,但这种延迟对你的CPU来说可能会产生全世界的差别。请试一试。 - jakebird451
现代计算机如何在向串行端口写入时出现困难? serial.Serial().write() 在写入时不会阻塞吗?这似乎为 CPU 执行其他任务提供了充足的时间? - Bittrance
显然,这是一个循环问题。@jakebird451 我会尝试一下。但是,在9600波特率下,串行缓冲区可能会被淹没。我想我必须在微处理器中实现一些切换代码。:( 谢谢。 - jhtong
@jakebird451:似乎不起作用,CPU 的消耗率甚至更高了。我想我还是坚持0.2秒,并实施一个切换过程来减少发送的命令数。不过还是谢谢你。 - jhtong
这不是循环问题,你只是误解了计算概念。想一想,你期望程序在不占用更多 CPU 时间的情况下“做更多”的事情,但事实并非如此。 - Zoran Pavlovic
3个回答

68
慢的CPU浪费的部分是“执行串行发送”的过程。只有一个短暂休眠的while循环会使用可忽略的CPU。
你能展示一下串行发送的代码吗?也许有一种方法可以加速它。
在这个相当慢的CPU上,我看到了这个:
import time
while True: time.sleep(0.2)      # 0% CPU
while True: time.sleep(0.02)     # 0% CPU
while True: time.sleep(0.002)    # 0.5% CPU
while True: time.sleep(0.0002)   # 6% CPU
while True: time.sleep(0.00002)  # 18% CPU

现在在循环中做一些额外的工作:

import time
while True: range(10000) and None; time.sleep(0.2)      # 1% CPU
while True: range(10000) and None; time.sleep(0.02)     # 15% CPU
while True: range(10000) and None; time.sleep(0.002)    # 60% CPU
while True: range(10000) and None; time.sleep(0.0002)   # 86% CPU

我在解释器中运行了这些代码,并使用ctrl-C停止了每个while循环。


或者,我可以使用开关限制串行传递,但这意味着需要重新编程嵌入式设备。代码看起来像这样: command = 'w'while True: if (command != x): # 在此处pyserial发送字符串<command>,在本例中为w。<command>通过外部处理程序更改。 else: # 告诉pyserial关闭连接。 - jhtong
看起来我需要在计算机和微处理器两端实现一个切换检查,以减少发送的命令数量。然后坚持使用sleep(0.2),以降低CPU使用率。即保存最后一条命令,如果已经发送,则不再发送。同时,微处理器将等待停止命令'x'。如果没有收到,它将继续以自己的速度处理当前/先前的命令。 - jhtong
如果你的微控制器将“以自己的速度继续处理当前命令”,那么在你的Python代码中不需要while循环。我怀疑任何串口通信库都不会“要求”你调用任何while循环。也许你应该重新阅读库文档,因为听起来你可能使用不正确。 - Zoran Pavlovic

7
关于您对Joachim回答的评论:
那么您的微控制器代码需要重新设计。否则,您只是将通用计算机变成了一个无用的“微控制器”,反复迭代不必要的代码,因此CPU使用率为100%。您错误地使用计算机的另一个症状是,硬件电机的速度取决于您通过串行接口发送命令的速度。您需要使用托管高级逻辑的计算机来“命令”它。而您的微控制器需要处理低级别、重复的电机控制。

3

你需要在速度和CPU负载之间权衡选择。

如果你必须发送短暂的数据爆发,同时在消息之间不做太多处理,那么也许你可以短时间内承受较高的CPU负载,因为平均值可能仍然很低。


谢谢,不过这可能意味着重新编程微控制器以使用开关。它必须向前移动,因此必须发送“w”。如果没有检测到“w”键,则电机不会移动。因此,如果发送得太慢,电机会移动得更慢。 - jhtong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接