我正在制作一个用Python运行模拟的程序,带有一个wxPython接口。在程序中,您可以创建模拟,程序为您渲染(=计算)它。有时渲染可能非常耗时。
当用户启动模拟并定义初始状态时,我希望程序在后台连续渲染模拟,而用户可能在程序中执行不同的操作。有点类似于填充的YouTube风格的条形图:您可以仅在渲染点播放模拟。
我应该使用多个进程还是多个线程或者什么?人们告诉我使用multiprocessing
包,我检查了它看起来不错,但我也听说过程与线程不同,不能共享大量信息(我认为我的程序需要共享很多信息。)另外我也听说过Stackless Python:它是一个单独的选项吗?我不知道。
请告知。
答案 0 :(得分:18)
“我检查了它看起来不错,但我也听说过程与线程不同,不能分享很多信息......”
这只是部分正确。
线程是进程的一部分 - 线程简单地共享内存。这是一个问题作为一个帮助 - 两个随意忽视彼此的线程可能会覆盖内存并造成严重问题。
然而,流程通过许多机制共享信息。 Posix管道(a | b
)表示处理a和处理b共享信息 - 写入和b读取信息。对于很多事情来说,这非常有效。
操作系统会在您创建流程时尽快将流程分配给每个可用核心。这很好地解决了很多问题。
Stackless Python与此讨论无关 - 它更快,并且具有不同的线程调度。但我不认为线程是最佳途径。
“我认为我的计划需要分享大量信息。”
你应该先解决这个问题。然后,确定如何围绕信息流构建流程。 “管道”非常容易和自然地做;任何shell都会简单地创建管道。
“服务器”是另一种架构,其中多个客户端进程获取和/或将信息放入中央服务器。这是分享信息的好方法。您可以使用WSGI参考实现来构建简单,可靠的服务器。
答案 1 :(得分:14)
<强>更新强>
深入分析
使用线程很容易。但是,如果您在返回之前调用了长时间的C例程,那么如果您的C例程没有释放锁定,那么这可能不是一个选择。
如果非常受cpu功率限制并且您需要最大响应能力,请使用多处理。
不要使用stackless,我之前已经使用了segfault,并且除非你使用数百个或更多的线程,否则线程几乎相同。
答案 2 :(得分:14)
今年在Pycon进行了多次处理。外卖消息是“只使用多处理,除非你确定你有一个问题会解决,用线程无法解决;否则,使用线程。”
进程有很多开销,所有要在进程之间共享的数据必须是可序列化的(即pickleable)。
您可以在此处查看幻灯片和视频: http://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-multiprocessing-in-python-1957019
答案 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的创建者)特别批评了多线程。引用here,here,here和here的一些材料支持这样的结论。
希望有所帮助,祝你好运。
答案 6 :(得分:1)
为了简单起见,我总是喜欢多个线程,但是亲和力存在一个真正的问题。没有办法(我知道)告诉Python的线程实现绑定到特定的处理器。这对你来说可能不是问题,它听起来应该不是。除非你有充分的理由不这样做,否则听起来你的问题可以通过Python的线程实现轻松解决。
如果您决定使用已处理的,则可以通过多种方式完成子进程之间的共享信息:tcp / udp连接,共享内存或管道。它确实增加了一些开销和复杂性。
答案 7 :(得分:1)
非常困惑。 BastienLéonard正确地指出GIL将以任何有用的方式阻止任何使用线程的能力。他的参考指出:
“在语言中使用全局解释器锁定有效地限制了 通过单个并发可达到的并行数量 多线程的解释器进程。如果这个过程差不多 纯粹由解释代码组成,不在外面进行调用 解释器很长一段时间(可以释放锁定 在它处理的那个线程上的GIL上,有可能存在 在a上运行进程时,速度几乎没有增加 多处理器机器。由于与CPU绑定线程的信令,它 即使在单处理器上也可能导致显着减速。“
在这种情况下,多处理是明智的选择。根据我自己的经验,Python + MT对用户没有明显的好处。
答案 8 :(得分:0)
听起来你想要线程化。
你描述它的方式,听起来就像有一件事实际占用了大量的CPU ......模拟的实际运行。
通过在模拟运行时允许用户交互和图形更新,您要获得的是响应更快的显示。这正是python的线程构建的原因。
这不会让您获得利用系统上多个核心/处理器的能力。我不知道你的模拟是什么样的,但如果它是CPU密集型的,它可能是分裂的好选择。在这种情况下,您可以使用多处理在单独的核心/处理器上运行模拟的单独部分。但是,这不是一件容易的事情......现在需要一些方法来传递数据,然后在进程之间传递第四个,因为单独的进程无法轻松访问相同的内存空间。