多处理还是多线程?

时间:2009-04-08 21:44:44

标签: python multithreading multiprocessing multicore python-stackless

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

当用户启动模拟并定义初始状态时,我希望程序在后台连续渲染模拟,而用户可能在程序中执行不同的操作。有点类似于填充的YouTube风格的条形图:您可以仅在渲染点播放模拟。

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

请告知。

9 个答案:

答案 0 :(得分:18)

“我检查了它看起来不错,但我也听说过程与线程不同,不能分享很多信息......”

这只是部分正确。

线程是进程的一部分 - 线程简单地共享内存。这是一个问题作为一个帮助 - 两个随意忽视彼此的线程可能会覆盖内存并造成严重问题。

然而,

流程通过许多机制共享信息。 Posix管道(a | b)表示处理a和处理b共享信息 - 写入和b读取信息。对于很多事情来说,这非常有效。

操作系统会在您创建流程时尽快将流程分配给每个可用核心。这很好地解决了很多问题。

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

“我认为我的计划需要分享大量信息。”

你应该先解决这个问题。然后,确定如何围绕信息流构建流程。 “管道”非常容易和自然地做;任何shell都会简单地创建管道。

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

答案 1 :(得分:14)

  • 无Stackless :使用1个cpu。 “Tasklets”必须自愿产生。抢占选项不会一直有效。
  • 线程:使用1个cpu。在运行20-100个python操作码后,本机线程会在一定程度上随机共享时间。
  • 多处理:使用多个cpu

<强>更新

深入分析

使用线程很容易。但是,如果您在返回之前调用了时间的C例程,那么如果您的C例程没有释放锁定,那么这可能不是一个选择。

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

不要使用stackless,我之前已经使用了segfault,并且除非你使用数百个或更多的线程,否则线程几乎相同。

答案 2 :(得分: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/

答案 3 :(得分:10)

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

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

在多个线程上使用多个进程的一个优点是,可以更轻松地扩展程序以使用通过网络协议进行通信的多台计算机。

例如,您可以在8台双核计算机上运行16个进程,但在四核计算机上不会有超过4个线程的优势。如果您需要通信的信息量很少,则多处理可能更有意义。

至于你所描述的youtube风格,我会说这表明多处理。如果遵循MVC方法,则GUI不应包含模型(计算结果)。通过多进程,您可以与可以报告已有数据的工作管理器进行通信。

答案 4 :(得分:5)

由于GIL:link text,CPython无法同时执行多个线程。

我认为线程仍有可能提升您的应用程序,例如:一个线程可能阻塞I / O而另一个线程可以阻塞I / O.

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

答案 5 :(得分:4)

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

顺便提一下,Mozilla项目的几个成员(特别是Brendan Eich,Mozilla的CTO和JavaScript的创建者)特别批评了多线程。引用herehereherehere的一些材料支持这样的结论。

希望有所帮助,祝你好运。

答案 6 :(得分:1)

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

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

答案 7 :(得分:1)

非常困惑。 BastienLéonard正确地指出GIL将以任何有用的方式阻止任何使用线程的能力。他的参考指出:

  

“在语言中使用全局解释器锁定有效地限制了   通过单个并发可达到的并行数量   多线程的解释器进程。如果这个过程差不多   纯粹由解释代码组成,不在外面进行调用   解释器很长一段时间(可以释放锁定   在它处理的那个线程上的GIL上,有可能存在   在a上运行进程时,速度几乎没有增加   多处理器机器。由于与CPU绑定线程的信令,它   即使在单处理器上也可能导致显着减速。“

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

答案 8 :(得分:0)

听起来你想要线程化。

你描述它的方式,听起来就像有一件事实际占用了大量的CPU ......模拟的实际运行。

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

这不会让您获得利用系统上多个核心/处理器的能力。我不知道你的模拟是什么样的,但如果它是CPU密集型的,它可能是分裂的好选择。在这种情况下,您可以使用多处理在单独的核心/处理器上运行模拟的单独部分。但是,这不是一件容易的事情......现在需要一些方法来传递数据,然后在进程之间传递第四个,因为单独的进程无法轻松访问相同的内存空间。