天真地使用Python多处理会遇到什么问题?

时间:2009-12-18 01:19:14

标签: python multiprocessing

我们正在考虑使用复杂的GUI重新分解大型应用程序,该GUI以与后端分离的方式隔离,以使用新的(Python 2.6)多处理模块。 GUI /后端接口使用Queues和双向交换的Message对象。

我刚刚总结的一件事(暂时,但随意确认)是在多处理界面中不会保留“对象标识”。目前,当我们的GUI向后端发布消息时,它希望返回相同的消息,并将结果附加为属性。在某些情况下,它使用对象标识(if received_msg is message_i_sent:)来标识返回的消息......这似乎不适用于多处理。

这个问题是要问你在实际使用中看到了什么样的“陷阱”可以想象人们会在天真地使用多处理模块遇到,尤其是在重构中现有的单流程应用程序。请说明您的答案是否基于实际经验。为此问题提供可用的解决方法的奖励点。

编辑:虽然我对这个问题的意图是收集一般的问题的描述,但我认为我犯了两个错误:我从一开始就把它变成了社区维基(这可能会让很多人忽视它,因为他们不会得到声望点),而且我包含了一个过于具体的例子 - 虽然我很欣赏答案 - 可能让很多人错过了一般回复的请求。我可能会在一个新问题中重新说出来并重新提出这个问题。就目前而言,我接受一个答案最好只是关于这个问题,只要它与我所包含的具体例子有关。感谢那些做出回答的人!

3 个答案:

答案 0 :(得分:2)

我本身并没有使用过多处理,但所提出的问题类似于我在其他两个领域的经验:分布式系统和对象数据库。 Python对象标识可能是一种祝福和诅咒!

对于一般问题,如果您正在重构的应用程序可以确认异步处理任务,则会有所帮助。如果没有,您通常会最终管理锁定,并且通过使用单独的进程可能获得的大部分性能将在等待这些锁定时丢失。我还建议您花时间构建一些脚手架来调试跨进程。真正的异步流程往往比心灵能够持有和验证的更多 - 或者至少是我的想法!

对于概述的具体情况,我会在排队和返回项目时在进程边界管理对象标识。发送要处理的任务时,使用id()注释任务,并使用id()作为键将任务实例存储在字典中。更新/完成任务后,通过id()从字典中检索确切的任务,并将新更新的状态应用于该任务。现在,将保持确切的任务,从而保持其身份。

答案 1 :(得分:1)

当然,测试非单例对象上的身份(例如“a is None”或“a is False”)通常不是一个好习惯 - 它可能很快,但是一个非常快速的解决方法会是为了“==”测试交换“是”并使用增量计数器来定义身份:

# this is not threadsafe.
class Message(object):
    def _next_id():
       i = 0
       while True:
            i += 1
            yield i
    _idgen = _next_id()
    del _next_id

    def __init__(self):
        self.id = self._idgen.next()

    def __eq__(self, other):
        return (self.__class__ == other.__class__) and (self.id == other.id)

这可能是一个想法。

另外,请注意,如果你有大量的“工作进程”,内存消耗可能远远大于基于线程的方法。

答案 2 :(得分:1)

您可以尝试我的项目GarlicSim中的persistent包。这是LGPL'。

http://github.com/cool-RR/GarlicSim/tree/development/garlicsim/garlicsim/misc/persistent/

(其中的主要模块是persistent.py

我经常这样使用它:

# ...
self.identity = Persistent()

然后我有一个跨进程保留的标识。