24

我正在制作一个程序,用于在 Python 中运行模拟,带有 wxPython 接口。在程序中,您可以创建一个模拟,程序会为您渲染(=计算)它。渲染有时会非常耗时。

当用户开始模拟并定义初始状态时,我希望程序在后台连续渲染模拟,而用户可能在程序中做不同的事情。有点像一个充满了 YouTube 风格的栏:您只能播放模拟到渲染的点。

我应该使用多个进程或多个线程还是什么?人们告诉我要使用这个multiprocessing包,我检查了一下,它看起来不错,但我也听说进程与线程不同,不能共享很多信息(我认为我的程序需要共享很多信息。 ) 此外,我还听说过 Stackless Python:它是一个单独的选项吗?我不知道。

请指教。

4

9 回答 9

18

“我查了一下,看起来不错,但我也听说进程不像线程,不能共享很多信息……”

这只是部分正确。

线程是进程的一部分——线程共享内存微不足道。这既是一个帮助问题,也是一个问题——两个随意忽视彼此的线程可能会覆盖内存并产生严重的问题。

然而,进程通过许多机制共享信息。Posix 管道 ( a | b) 意味着进程 a 和进程 b 共享信息——a 写入它,b 读取它。这对很多事情都非常有效。

操作系统将在您创建进程时尽快将进程分配给每个可用内核。这对很多事情都非常有效。

Stackless Python 与本次讨论无关——它更快并且具有不同的线程调度。但我不认为线程是最好的途径。

“我认为我的程序需要分享很多信息。”

你应该先解决这个问题。然后,确定如何围绕信息流构建流程。一个“管道”是很容易和自然的;任何外壳都会轻松创建管道。

“服务器”是另一种架构,其中多个客户端进程获取和/或将信息放入中央服务器。这是共享信息的好方法。您可以使用 WSGI 参考实现来构建简单、可靠的服务器。

于 2009-04-08T22:21:29.217 回答
14
  • 无堆栈:使用 1 个 CPU。“小任务”必须自愿让步。抢占选项并非始终有效。
  • 线程:使用 1 个 CPU。在运行 20-100 个 python 操作码后,本机线程会随机共享时间。
  • 多处理:使用多个 cpu

更新

深入分析

轻松使用螺纹。但是,如果您调用需要很长时间才能返回的 C 例程那么如果您的 C 例程不释放锁,这可能不是一个选择。

如果CPU 功率非常有限并且您需要最大的响应能力,请使用多处理。

不要使用无堆栈,我之前有过段错误,除非你使用数百个或更多线程,否则线程几乎是等效的。

于 2009-04-08T22:22:13.757 回答
14

今年在 Pycon 上有一个关于多处理的精彩演讲。外卖消息是“仅使用多处理,除非你确定你有一个问题可以解决,不能用线程解决;否则,使用线程。”

进程有很多开销,所有要在进程之间共享的数据都必须是可序列化的(即pickleable)。

您可以在此处查看幻灯片和视频:http: //blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-multiprocessing-in-python-1957019

http://us.pycon.org/2009/conference/schedule/event/31/

于 2009-04-09T01:21:33.620 回答
10

进程有自己的内存空间。它使共享信息变得更加困难,但也使程序更安全(更少需要显式同步)。也就是说,进程可以在只读模式下共享相同的内存。

线程创建或终止的成本更低,但主要区别在于它与同一进程中的其他线程共享内存。这有时是有风险的,此外,使进程崩溃会杀死所有线程。

在多个线程上使用多个进程的一个优点是可以更轻松地扩展您的程序以与通过网络协议进行通信的多台机器一起工作。

例如,您可能会在 8 台双核机器上运行 16 个进程,但不会从四核机器上超过 4 个线程中受益。如果您需要传达的信息量很少,那么多处理可能更有意义。

至于您所描述的 youtube 风格,我想说的是多处理。如果您遵循 MVC 方法,您的 GUI 不应该还包含模型(计算结果)。使用多进程,您可以与可以报告哪些数据已经可用的工作经理进行通信。

于 2009-04-08T22:48:35.970 回答
5

由于 GIL: link text,使用 CPython 多个线程不能同时执行。

我认为线程仍然有可能提升您的应用程序,例如,一个线程可能会阻塞 I/O,而另一个线程会做一些工作。

如果您从未使用过线程,我建议您先尝试一下。它将在任何其他语言中都很有用,并且您会在网络上找到很多资源。然后,如果您意识到需要更多并行性,您仍然可以切换回进程。

于 2009-04-08T22:41:01.183 回答
4

如果您想阅读关于 Mozilla 中多线程的冗长讨论,请考虑查看始于 2000 年的讨论。讨论不一定能回答您的问题。但是,这是一个深入的讨论,我认为它很有趣且内容丰富,我认为这可能非常有价值,因为您提出了一个困难的问题。希望它能帮助您做出明智的决定。

顺便说一句,Mozilla 项目的一些成员(尤其是 Brendan Eich,Mozilla 的 CTO 和 JavaScript 的创建者)对多线程尤其持批评态度。这里这里这里这里引用的一些材料支持这样的结论。

希望有帮助,祝你好运。

于 2009-04-14T16:35:01.890 回答
1

为了简单起见,我总是更喜欢多线程,但亲和力存在一个真正的问题。没有办法(据我所知)告诉 Python 的线程实现绑定到特定的处理器。这对你来说可能不是问题,听起来不应该是这样。除非您有充分的理由不这样做,否则听起来您的问题可以通过 Python 的线程实现轻松解决。

如果您决定使用已处理,子进程之间的共享信息可以通过多种方式完成:tcp/udp 连接、共享内存或管道。它确实增加了一些开销和复杂性。

于 2009-04-08T21:52:44.403 回答
1

很不解。Bastien Léonard 正确地指出,GIL 将阻止以任何有用的方式使用线程的能力。他的参考资料指出:

“在一种语言中使用全局解释器锁有效地限制了通过具有多个线程的单个解释器进程的并发性可达到的并行量。如果该进程几乎完全由解释代码组成并且不会长时间在解释器之外进行调用一段时间(这可以在它处理时释放该线程上 GIL 上的锁),在多处理器机器上运行该进程时,速度可能几乎没有增加。由于使用 CPU-bound 线程发出信号,它即使在单个处理器上,也可能导致显着减速。”

在这种情况下,多处理是明智的选择。根据我自己的经验,Python + MT 对用户没有明显的好处。

于 2016-03-13T16:01:39.027 回答
0

听起来你想要线程。

按照您描述的方式,听起来只有一件事实际上占用了大量 CPU……模拟的实际运行。

通过在模拟运行时允许用户交互和图形更新,您想要获得的是响应更快的显示。这正是 python 的线程的目的。

这不会让您获得利用系统上多个内核/处理器的能力。我不知道你的模拟是什么样的,但如果它是 CPU 密集型的,它可能是一个很好的拆分候选者。在这种情况下,您可以使用多处理在不同的内核/处理器上运行模拟的不同部分。然而,这并不是微不足道的……您现在需要某种方式在进程之间传回和第四次数据,因为单独的进程无法轻松访问相同的内存空间。

于 2009-04-09T16:17:00.057 回答