我有一个 RPI3B+ 正在处理一个包含 30 个左右不同 IO 模块的项目。硬件资源是固定的,无法升级,所以我们有4个核心。 IO 包括键盘、HAT 上的电机、i2c 和 PWM 驱动的 LED、显示图像和视频的屏幕、IMU、各种二进制 GPIO、声音输出等。有很多。这是一个大型艺术装置。
其中一些 IO 是快速启动并忘记的,而其他 IO 必须由程序管理其状态(即某些伺服器必须比其他伺服器移动得更快/更慢,在不同时间写入它们的 PWM 值,大量睡眠()) 。我们并不是真正的 IO 绑定,因为大多数输出不需要返回输入,但如果我为每个输出创建一个进程,那将产生大量开销。也许线程/异步?
嗯,一些驱动输出的任务比其他任务更需要 CPU 密集度,当同时驱动其中一些或全部任务时,有时可能会加剧这种情况。并非所有功能都对功能至关重要,但有些绝对不能被中断。例如:
我有一个 IMU,可以跟踪项目在空间中的位置,为了防止整个项目失衡,IMU 的输出被映射到平衡伺服系统。这绝对是至关重要的。
不要错过 USB 键盘的输入也很重要。但是对于我们需要驱动的许多 LED 和电机,如果程序受到 CPU 限制,它们可能会稍微滞后。那么,也许是多处理?
大多数驱动 IO 的模块不需要知道其余模块的状态,因此程序可以用一个值初始化它们,它们会及时完成自己的工作并让应用程序的其余部分运行.
SO,尽管如此,我可以创建一些进程,并将更关键的 IO 放在自己的进程中,同时将可能的 CPU 密集型问题制造者组织到单独进程中的线程中。这是两者都使用的好案例吗?
您使用了错误的工具来完成这项工作:)
如果您想要任何类型的实时甚至近实时控制(电机对 IMU 做出反应),您需要放弃单板计算机 (SBC)。 SBC 的处理能力通常非常有限,并且在后台运行操作系统和多个不同的软件实例。当CPU有时间处理你的请求时(即使它们被定义为中断,因此是异步的),已经太晚了(问我怎么知道......)。
您需要使用微控制器(如果您想留在同一个生态系统中,像 pi pico 这样的东西就足以胜任这项工作)来完成所有艰苦的工作,然后 pi 可以完成计算成本更高的部分代码(我不认为你的案例有任何这样的代码,但是对于机器人应用程序来说,诸如映射和导航之类的事情被卸载到pi,而MCU则执行诸如读取IMU、电机编码器、控制电机PWM等之类的事情,并且将该信息发送回 pi,以便它了解机器人的状态)。
回到你原来的问题:多处理几乎不是答案,它比多线程慢得多。您描述的情况是 I/O 限制,而不是 CPU 限制(如果您可以运行一些基准测试,我向您保证会是这种情况),这应该可以通过多线程轻松解决。此外,如果您确实受 CPU 限制,您可能需要考虑使用 Cython 创建代码的优化版本。只要您小心处理并将 Numpy 数组作为内存视图传递给 Cython,您甚至可以释放 GIL 并直接使用不同的核心/线程处理共享内存。同样,这是通过多线程而不是多处理来实现的。如果您需要性能,请远离多重处理,因为它需要大量消息传递和内存副本。