Python 使用昂贵的初始化优化多处理池
下面是一个完整的简单工作示例Python 使用昂贵的初始化优化多处理池,python,python-3.5,python-multiprocessing,pool,object-initializers,Python,Python 3.5,Python Multiprocessing,Pool,Object Initializers,下面是一个完整的简单工作示例 import multiprocessing as mp import time import random class Foo: def __init__(self): # some expensive set up function in the real code self.x = 2 print('initializing') def run(self, y): time.
import multiprocessing as mp
import time
import random
class Foo:
def __init__(self):
# some expensive set up function in the real code
self.x = 2
print('initializing')
def run(self, y):
time.sleep(random.random() / 10.)
return self.x + y
def f(y):
foo = Foo()
return foo.run(y)
def main():
pool = mp.Pool(4)
for result in pool.map(f, range(10)):
print(result)
pool.close()
pool.join()
if __name__ == '__main__':
main()
我如何修改它,使Foo只由每个worker初始化一次,而不是由每个任务初始化一次?基本上我希望init调用4次,而不是10次。我使用的是python 3.5,这是最明显的延迟加载
_foo = None
def f(y):
global _foo
if not _foo:
_foo = Foo()
return _foo.run(y)
处理此类问题的预期方法是通过
Pool()
构造函数的可选initializer
和initargs
参数。它们的存在正是为了在创建辅助进程时为您提供一种只执行一次的方法。因此,例如,添加:
def init():
global foo
foo = Foo()
并将池的创建更改为:
pool = mp.Pool(4, initializer=init)
如果需要将参数传递给每进程初始化函数,那么还需要添加一个适当的initargs=…
参数
注意:当然,您还应该删除
foo = Foo()
来自f()
的行,以便您的函数使用由init()
创建的全局foo
,如果只初始化一次类,然后将其复制到每个工作者,是否可以?@BrendanAbel我认为可以。这意味着对象必须是可酸洗的?初始化后对象从未发生变化,所以我不知道为什么复制会失败。多处理与多线程不同。它们有着截然不同的特征。很抱歉问题标题中出现了混淆。为什么您有一个从未被引用过的全局\u foo
?请您在此上下文中解释全局关键字。我在文档中看到了初始值设定项,但没有考虑/了解“全局”,因此我不知道如何使其工作。谢谢您刚才的编辑:您还需要使用初始化函数创建的foo
。初始化函数运行一次并结束,因此它所做的任何更改都必须在全局范围内可见,以便以后的其他函数(例如由map()
调用)可以受益。否。没有任何东西是跨进程共享的global
从第一天起就开始使用Python,这比多处理
甚至是一个模块的想法早了很多年<代码>全局
与进程(或线程)无关。在上下文中,它只是告诉init()。在多处理中,每个进程都有自己独特的模块全局名称空间。