如何根据fork()复制状态重构Python代码
我正在开发一个大型的ish-Python代码库,这个代码库已经存在了十多年了。所讨论的应用程序利用forking实现并行性 基本前提是,用户要求程序构建一个特定的目标,我们计算出目标的依赖图,然后从构建图中的拓扑分区计算出一些我们可以并行执行的任务。然后,我们分叉一些进程来并行执行这些任务(来自分区) 这一切都很有效。但是,我想重构它,使其不依赖于如何根据fork()复制状态重构Python代码,python,multiprocessing,fork,state,Python,Multiprocessing,Fork,State,我正在开发一个大型的ish-Python代码库,这个代码库已经存在了十多年了。所讨论的应用程序利用forking实现并行性 基本前提是,用户要求程序构建一个特定的目标,我们计算出目标的依赖图,然后从构建图中的拓扑分区计算出一些我们可以并行执行的任务。然后,我们分叉一些进程来并行执行这些任务(来自分区) 这一切都很有效。但是,我想重构它,使其不依赖于fork()。特别是,子进程中主进程的状态依赖性是一个问题 重构有几个激励因素: 我希望Linux和Linux之间的代码尽可能相似 和Windows(
fork()
。特别是,子进程中主进程的状态依赖性是一个问题
重构有几个激励因素:
基本上,我在寻求如何从整体上最好地解决这个问题的建议。我提出以下范例 Master是一个单独的进程,它执行所有依赖项解析、图形分区等操作,直至单个作业。因此,系统状态只有一个副本 使用
子进程
或多处理
或操作系统
卸载这些叶作业
卸载机制越简单,平台独立性越强:)
叶子当然是异步的,因此您需要一个处理异步通知的框架——您可以使用gevent
或一些实现未来
的库。如果你是真正的铁杆,twisted
。Python3.x还引入了可能有用的asyncio
您还可以将资源/执行器池与特别通知一起使用,例如,我认为可以相对简单地使用递归函数或递归生成器来实现这些通知。@AlexShkop multiprocessing module最终是我想要结束的地方。然而,真正的问题是解决对使用分叉复制的状态的依赖性。请注意,在Linux上,多处理会产生带有fork(状态复制)的新进程,而在Windows上(没有fork)则不会。我不知道为什么必须重用指向文件描述符的指针。听起来是个坏主意。无论如何,您必须区分数据和助手、访问者等。FD不是数据。您可以将所有数据放在共享位置(例如sqlite?)。现在,您可以简单地在同一共享结构上运行独立的进程。这基本上就是当前代码所做的(主进程中的完全依赖关系解析,要构建的原子目标被发送到子进程)。问题是要构建的目标(由依赖项解析确定)是a)具有大量当前无法序列化的状态的复杂对象(包括文件描述符)和b)很难进入可以序列化的状态(由于我们的代码库的性质)。只要在这些“叶子”中不使用Python执行繁重的计算,也许可以将它们分解为一系列
os.system
或subprocess.Popen
调用?在这种情况下,您可以完全使用线程
,或者如果外部操作的总数太大,gevent
。重点是将目标逻辑移到主流程中。我想我真正问题的答案是“如果你不能很好地描述一个构建任务而不进行分叉,那么代码需要重构”。没有一种神奇的方法能够以平台无关的方式提供类似于fork的功能。将此答案标记为已接受,因为它最接近“正确”。一点OT:流程中最接近fork
的是cPickle.loads(cPickle.dumps(obj))
。它甚至比copy.deepcopy()
更好。但是,要使自定义类和资源可拾取/可查找,可能需要做很多工作。