0

项目描述:

将现有的“C”程序(主控件)连接到 Python GUI/Widget。为此,我使用了 FIFO。C 程序旨在查看基于帧的遥测。

Python GUI 执行两个功能:

  1. 根据用户的需要(单个 .py 文件,不同用户编写的脚本)通过 GUI 小部件运行/创建绘图(可能通过 matplotlib 创建)
  2. 在创建后将帧号中继到 python 绘图脚本,以便在从主程序获得帧号后它们可以“更新”自己。

我有几个问题——了解这里看到的多处理与多线程的优缺点:Multiprocessing vs Threading Python

实施注意事项:

  1. 我猜,在基于信号的架构中通过线程创建的图太多,在更新它们方面可能会变得滞后。我不确定它们什么时候会受到 CPU 的限制……大多数情节会更新几行系列,有些可能会更新图像。无论创建方法如何,无论我选择哪种方式,它都可能会滞后。

  2. 我不确定打开 30 个 python 进程是什么,每个进程使用 matplotlib 制作一两个绘图对机器或其资源有什么作用。我在我的系统上看到一个简单的 matplotlib 图的 RSS(分配的内存)为 117M,所以我认为如果通过为每个图打开单独的进程来完成,单个用户绘制 30 个图不会限制系统内存。(16 GB,32 核 Linux Box,同时有多个用户)

问题:

  1. 我是否应该通过线程或进程打开绘图,并且其中一个会比另一个滞后?
  2. 如果我使用线程,是否有人知道在单个线程上变得滞后之前需要更新多少 matplotlib 数字?
  3. 如果我将绘图创建为进程,我应该使用 multiprocessing 包吗?我猜这个 API 可以直接在进程之间传递帧号?
  4. 鉴于我有可用的多处理,尝试通过 POpen 打开进程可能很愚蠢,对吗?我猜是这种情况,因为如果我这样做,我将不得不自己设置所有管道/IPC,这会更有效吗?
4

1 回答 1

0

所以我能够以两种方式实现这个项目——有和没有多进程。

  1. 我在 PyQt GUI 中有一个主进程,其线程从控制 C 程序帧号的管道中读取。
  2. 当用户选择绘图(.py 脚本)时,可以选择在一批绘图上按下“执行”按钮,从而将它们保持在主进程中。从这一点开始,如果框架更新,绘图将连续更新。减速开始几乎立即发生在少数地块之后,但对于 10 到 20 个简单的时间序列地块来说并不令人望而却步。
  3. 有一个替代按钮允许使用另一个进程进行处理。我能够使用 POpen 和命名管道或多处理和多处理队列来做到这一点。最干净的方法是让我的其他进程创建绘图 QObjects 并使用 pyqt 信号,其中每个其他进程通过在该进程中创建 QApplications 结束,但我必须使用 ctx = mp.get_context('spawn' ) 在 Linux 上,因为默认情况下 Linux 使用分叉,当我创建 QApplication 时,它认为 QApplication 已经在主进程中运行。这是我能够获得可预测的多处理行为的唯一方法,其中所有 matplotlib 图都将在替代过程中更新。

我读到 matplotlib 在网络上不是线程安全的,但是,pyqt 插槽从等待队列读取的线程发出,这似乎很好。

我选择该实施是为了让用户可以灵活地在同一进程中打开绘图或在另一个进程中打开批量绘图,而不是为每个进程预先确定数量的绘图,认为可能存在某些具有复杂更新的绘图,这些绘图是值得创建的他们自己的过程,可以这样选择。这也比每个进程的简单绘图浪费更少@每个进程至少 100MB,同一进程中的每个额外绘图仅需要 3MB 左右的额外内存。

最后一个细节是用户可能非常快速地切换帧。我让接收进程在非阻塞守护线程中读取并清空队列并仅获取最新信息。一旦发送了更新绘图的信号,绘图更新循环就会抓住一个线程锁,并且在更新方法释放线程锁后,读取守护进程再次能够发出更新。

实现基本思想的一些示例代码:https ://stackoverflow.com/a/49226785/8209352

于 2018-02-17T05:47:05.677 回答