多进程还是多线程?

24
我正在用Python编写一个程序,通过wxPython界面运行模拟。在程序中,您可以创建一个模拟,并由程序进行渲染(即计算)。有时渲染可能非常耗时。
当用户启动模拟并定义初始状态时,我希望程序在后台持续渲染模拟,而用户可以在程序中进行其他操作,就像YouTube样式的进度条:只能播放已经渲染过的部分。
我应该使用多个进程还是多个线程?人们告诉我要使用包,我查看了它,看起来不错,但我也听说进程不能像线程那样共享很多信息(我认为我的程序需要共享很多信息)。此外,我还听说过Stackless Python:这是另一个选择吗?我一点都不清楚。
请给予建议。

我对你的“我认为我的程序需要共享大量信息”感到担忧 - 你的意思是你还不确定吗?也许你应该做更多的设计工作。多进程模块与线程模块松散兼容,因此切换不应该是一个巨大的努力。但要注意GIL,这会让我更喜欢多进程。 - CyberFonic
9个回答

18

"我查看了一下,看起来不错,但我也听说进程与线程不同,不能共享很多信息..."

这只是部分正确的。

线程是进程的一部分--线程可以轻松地共享内存。这既是帮助也是问题--两个没有考虑彼此的线程可能会覆盖内存并创建严重的问题。

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

操作系统将尽快将您的进程分配给每个可用的核心。这对于许多事情非常有用。

无栈Python与此讨论无关--它更快,并具有不同的线程调度。但我认为线程不是最佳路线。

"我认为我的程序需要共享很多信息。"

您应该首先解决这个问题。然后,确定如何围绕信息流构建进程结构。 "管道"非常容易和自然;任何shell都可以轻松创建管道。

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


14
  • 无栈协程(Stackless):仅使用1个CPU。"Tasklets"必须自愿让出yield,而抢占选项并不总是有效。
  • 多线程(Threaded):仅使用1个CPU。本地线程在运行20-100个Python操作码后会有些随机的共享时间。
  • 多进程(Multiprocessing):使用多个CPU。

更新

深入分析

如果你需要调用需要较长时间才能返回的C例程,且该例程不释放锁,则使用多线程可能不是一个好选择,这时可以考虑使用无栈协程。

如果CPU性能受到非常严重限制,并且需要最大的响应能力,则使用多进程。

不要使用无栈协程,我曾经遇到过它导致程序崩溃的情况,而且除非你正在使用数百个或更多的线程,否则线程几乎与之等效。


5
这是我头一次听到有人说线程编程很容易。在我看来,编写高质量的线程代码非常困难。 - Bryan Oakley

14
今年在Pycon上有一个关于多进程的好讲座。主要观点是“只有在你确定存在无法使用线程解决的问题时,才应该使用多进程;否则,请使用线程。”进程有很多开销,并且所有需要在进程间共享的数据都必须是可序列化的(即可pickle)。您可以在此处查看幻灯片和视频:http://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-multiprocessing-in-python-1957019

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


3
很不幸,这与其他语言所采用的方式几乎完全相反。线程容易出错且受限于进程,而在Python中,你还要面对GIL问题,这更是雪上加霜。 - Kylotan
9
虽然有多个进程的运行时间开销比以前五到十年少了很多,但它们确实存在一些运行时间开销。然而,线程编码有很大的编程开销。编写好的线程代码需要聪明的人来完成,而调试它则需要非常聪明的人才能胜任。 - Bryan Oakley
1
这些幻灯片/演讲有更新的链接吗?当前的链接似乎失效了。 - Tyler
blip.tv 上有从2011年到2009年的视频。这似乎是2009年关于多进程的一个视频:http://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-multiprocessing-in-python-1957019 - gary
1
哦,"只使用X,除非Y,否则Z" 确实措辞晦涩难懂。 - ubershmekel

10

一个进程有自己的内存空间,这使得共享信息更加困难,但也使程序更安全(不需要显式同步)。话虽如此,进程可以以只读模式共享相同的内存。

线程更容易创建或销毁,但它与同一进程中的其他线程共享内存是主要区别。这有时是有风险的,在进程崩溃时将会杀死所有线程。

使用多个进程而不是多个线程的一个优点是更容易将程序扩展到通过网络协议通信的多台机器上运行。

例如,您可以在8台双核机器上潜在地运行16个进程,但在四核机器上最多只能从4个线程中获益。如果需要通信的信息量较低,则多进程可能更合理。

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


进程可以以只读模式共享同一内存。这对我来说非常有用。我该怎么做呢? - Ram Rachum
在大多数UNIX系统中,当您分叉一个进程(从另一个创建一个)时,它们应该共享相同的读取页面,直到写入为止。这可以节省程序代码的加载时间。但作为一种编程技术并不是那么有用。 - Uri
不幸的是,在Windows上并非如此(Windows没有可用的os.fork)。 - Jon Cage

5

由于全局解释器锁(GIL)的存在,CPython多线程无法同时执行:链接文本

我认为线程仍然可以提升应用程序的性能,例如一个线程可能会在I/O上阻塞,而另一个线程则可以执行一些工作。

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


4
如果您想阅读Mozilla中关于多线程的长篇讨论,请查看此处的讨论,该讨论始于2000年。该讨论并不一定回答您的问题,但它是一次深入的讨论,我认为它很有趣且富有启发性。考虑到您提出了一个困难的问题,希望它能帮助您做出明智的决策。
顺便说一下,Mozilla项目的几位成员(特别是JavaScript的创造者和Mozilla的CTO Brendan Eich)对多线程特别持批评态度。一些材料在这里在这里在这里以及在这里支持这样的结论。
希望这能帮到您,祝好运。

1
非常困惑。Bastien Léonard 指出 GIL(全局解释器锁)将停止任何有用的线程使用能力。他的参考文献指出:“在语言中使用全局解释器锁有效地限制了单个解释器进程通过并发实现的并行性数量。如果该进程几乎完全由解释代码组成,并且长时间不进行解释器外的调用(这可以释放处理该线程时 GIL 上的锁),那么在多处理器计算机上运行该进程时,速度增加很小。由于与 CPU 绑定的线程信号,甚至在单个处理器上也会导致显着减速。”因此,多处理是明智的选择。从我的经验来看,Python + MT 对用户没有明显的好处。

1

我总是喜欢使用多线程来简化问题,但亲和力确实存在一个真正的问题。据我所知,没有办法告诉Python的线程实现绑定到特定的处理器上。这可能对您来说不是问题,听起来似乎也不应该是问题。除非您有充分的理由不这样做,否则使用Python的线程实现可以轻松解决您的问题。

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


1
线程是一种非常自然的格式,适用于处理事件驱动GUI,并且它有助于避免进程间通信的痛苦(除非您的信息共享需求适合Shane提到的有限选项)。 - ojrac
1
  1. 线程会自动利用CPU中的所有核心吗?
  2. 你知道Stackless在这方面是如何适应的吗?
- Ram Rachum
关于线程的事情是它们通常在操作系统的控制下,而且所有操作系统都很好地分配负载到各个CPU上。这通常是您想要的行为。不过,您可以想象一些场景,您可能想要将单个任务绑定到单个CPU上。 - Shane C. Mason
5
Python的全局解释器锁规定一次只能有一个线程访问解释器。因此,使用Python的线程无法利用多核处理器。 - Jason Baker
1
Jason所说的是真的,GIL不允许在多个CPU上并发执行。我在陈述时应该更加清晰,操作系统决定在哪个CPU上运行,你会看到你的应用程序在执行过程中切换CPU。 - Shane C. Mason
谢谢Jason - 这对我来说是最重要的事情。 - Ram Rachum

0

听起来你需要线程。

按照你描述的方式,似乎有一件事情实际上需要很多CPU...即模拟的实际运行。你想要的是更具响应性的显示,允许用户交互和图形更新,同时模拟正在运行。这正是Python的线程所构建的。但这不会让你能够利用系统上的多个核心/处理器。我不知道你的模拟看起来像什么,但如果它真的那么耗费CPU,那么它可能是分割的一个好候选对象。在这种情况下,您可以使用多进程在单独的核心/处理器上运行模拟的不同部分。然而,这并不是微不足道的...你现在需要某种方法来在进程之间传递数据,因为单独的进程不能轻松地访问相同的内存空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接