5

问题:

我可以在 Windows 上以有效的方式将多处理模块与 gevent 一起使用吗?

设想:

我有一个基于 gevent 的 Python 应用程序在 Windows 上执行异步 I/O。该应用程序主要受 I/O 限制,但也存在较高 CPU 负载的峰值。此应用程序需要通过其标准输入和标准输出来控制控制台应用程序。我无法修改此控制台应用程序,用户将能够使用他自己的自定义应用程序,只有基于文本(行)的通信协议是固定的。

我有一个使用子进程和线程的工作实现,但我宁愿将整个基于子进程的通信代码与这些线程一起移动到一个单独的进程中,以将主应用程序转回单线程。我计划为此使用多处理模块。

预读:

我一直在网上搜索并阅读了一些源代码,所以我知道多处理模块正在使用基于 Windows 上命名管道的管道实现。一对 multiprocessing.queue.Queue 对象将用于与第二个 Python 进程通信。这些队列基于该管道实现,例如 IPC 将通过命名管道完成。

关键问题是,调用传入 Queue 的 get 方法是否会阻塞 gevent 的主循环。该方法有一个超时,所以我可以将它变成一个小超时的循环,但这不是一个好的解决方案,因为它仍然会在小时间段内阻塞 gevent,从而损害其低 I/O 延迟。

我也愿意接受有关如何规避在 Windows 上使用管道的整个问题的建议,众所周知,管道很困难,有时很脆弱。我不确定在 Windows 上是否可以使用基于共享内存的 IPC。也许我可以以一种允许使用网络套接字与子进程通信的方式包装控制台应用程序,众所周知,这与 gevent 配合得很好。

如果可能,请不要质疑我的主要用例。谢谢。

4

2 回答 2

1

Queue 的 get 方法确实是阻塞的。将它与超时一起使用可能会解决您的问题,但它绝对不是最干净的解决方案,而且最重要的是,它会无缘无故地引入额外的延迟。即使它没有阻塞,这也不是一个好的解决方案。仅仅因为非阻塞本身还不够,好的异步调用/API应该平滑地集成到使用中的I/O框架中。成为 Python 的 gevent、C 的 libevent 或 C++ 的 Boost ASIO。

最简单的解决方案是通过生成控制台应用程序并附加到其控制台输入和输出描述符来使用简单的 I/O。有两个主要因素需要考虑:

  • 您的客户编写客户端应用程序将非常容易。他们不必使用任何类型的 IPC、套接字或其他代码,这对许多人来说可能是非常困难的事情。使用这种方法,应用程序只会从标准输入读取并写入标准输出。
  • 使用这种方法测试控制台应用程序将非常容易,因为您可以手动启动它们,在控制台中输入文本并查看结果。
  • Gevent 非常适合这里的异步读/写。

但是,缺点是您必须启动此应用程序,不支持与它的并发通信,也不支持通过网络进行通信。对于初学者来说,甚至还有一个很好的例子

为了保持简单但更灵活,您可以使用 TCP/IP 套接字。如果客户端和服务器都在同一台机器上运行。此外,一个好的操作系统会使用 IPC 作为底层实现,所以它会很快。而且,如果您担心这种情况的性能,您可能根本不应该使用 Python 并查看其他技术。

甚至花哨的解决方案——使用ZeroC ICE。它是一种非常现代的技术,允许几乎无缝的进程间通信。它是一个CORBA杀手,非常容易使用。它被许多人大量使用,被证明是同类产品中速度最快的并且坚如磐石。该解决方案的美妙之处在于您可以无缝集成多种不同语言的程序,例如 Python、Java、C++ 等。但这需要您花一些时间来熟悉一个概念。如果您决定采用这种方式,只需花一天时间阅读文档。

希望能帮助到你。祝你好运!

于 2011-02-24T14:49:17.517 回答
0

你的问题已经很老了。尽管如此,我还是想推荐http://gehrcke.de/gipc,我相信它会以非常直接的方式解决所概述的挑战。基本上,它允许您在应用程序的任何位置(也在 Windows 上)集成基于多处理的子进程。与对象的交互Process(例如调用join())是 gevent 合作的。通过其管道管理,它允许协作阻止进程间通信。然而,在 Windows 上,IPC 目前的效率远低于 POSIX 兼容系统(因为非阻塞 I/O 是通过线程池模拟的)。根据应用程序的 IPC 消息量,这可能重要也可能不重要。

于 2013-02-11T20:18:33.220 回答