大家好,
我在使用 python 为我的问题选择策略时遇到困难。 我有两个摄像头(将来可能会更多)连接到我的本地网络,并且想要获取两个流,对它们进行一些图像处理,并在将来将它们流式传输到本地 http 服务器。
我的第一个问题是,从相机读取帧,主要是 IO 密集型还是 CPU 密集型。
其次,我想知道是否/何时选择多处理路线,我应该如何实现它。首先,我有一个“三层结构”的想法,其中获取帧是由一个处理器在“DAL”层中完成的,由另一个处理器完成处理,也许将来第三个处理器会处理所有的 http 内容。 (http服务器是另一个时间)。
但是经过一些研究后,我不确定这是正确的方法吗?也许一个处理器应该处理从相机收集的所有 IO,进行处理并将其流式传输到 http 服务器。
有比我更有经验的人可以给我一些见解吗?
我有一些使用 python 和 opencv 的经验,但没有使用任何多线程/处理库,因为它更多的是论文的概念证明。
感谢您阅读这篇头脑风暴
相机规格为: 1080x720分辨率 帧率 160 fps 使用 GigE Vision 协议
我的第一个问题是,从相机读取帧,主要是 IO 密集型还是 CPU 密集型。
虽然网络 I/O 在某种程度上需要 CPU 密集型处理,但该处理发生在操作系统内核中。对于您的应用程序来说,它看起来就像 I/O。
其次,我想知道是否/何时选择多处理路线,我应该如何实现它。
您可以进行很多微调,但我认为坚持 KISS 原则并根据需要调整您的应用程序非常重要。
根据您的描述,我希望您的申请主要处于三个阶段之一:
如果您不想丢失帧,则应该(几乎)始终有一个专用线程执行步骤 1。否则 GigE 视觉会很高兴地丢弃它无法缓冲的帧。
对于步骤 2,您应该首先检查您的 OpenCV 处理是否在内部并行化,或者甚至可能使用 GPU 处理。在这种情况下,在其之上添加多处理或多线程几乎没有任何好处。
步骤 3 与步骤 1 类似,只是有一个线程随时准备发送图像,以保持网络层繁忙。由于此步骤涉及 TCP,因此并行使用多个 HTTP 连接可能会有所帮助。当然这取决于您的接收器。
就并行化而言,您最关心的是全局解释器锁(GIL)。 https://wiki.python.org/moin/GlobalInterpreterLock 但是,请注意该特定网站:
事后看来,GIL 并不理想,因为它会阻止多线程 CPython 程序在某些情况下充分利用多处理器系统。幸运的是,许多潜在的阻塞或长时间运行的操作(例如 I/O、图像处理和 NumPy 数字运算)都发生在 GIL 之外。因此,只有在多线程程序中,在 GIL 中花费大量时间来解释 CPython 字节码时,GIL 才会成为瓶颈。
换句话说,如果您所做的只是调用一些长时间运行的 C 函数,无论是网络 I/O 还是 OpenCV 处理,您都可以使用多线程。否则你可能需要多重处理。
请注意,多重处理会给整个处理带来更多成本,因为您需要将帧从一个应用程序复制到另一个应用程序。
总之,这是我的设置方法:
所有阶段都应与
queue.Queues
或 queue.SimpleQueues
连接。这些应该受到大小限制,以避免在处理停止时耗尽内存。
如果您发现确实需要多处理,则可以将队列替换为
multiprocessing.Queues
,并将所有线程替换为专用 multiprocessing.Processes
。或者,阶段 1 中的线程可以简单地为每个传入帧调用 multiprocessing.Pool.apply_async
,并通过 Queue
将 AsyncResult 对象传递到阶段 3。