Python 多进程:使用进程列表而不是池映射函数
我有一个多处理任务,其最简单的形式如下所示:Python 多进程:使用进程列表而不是池映射函数,python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我有一个多处理任务,其最简单的形式如下所示: def fun(x): y = setup() return y.f(x) pool = mp.Pool(4) pool.map(fun, my_list) 但是,setup()非常昂贵,因此我只想在每个过程中执行一次,而不是在我的列表中的每个项目执行一次 我也不想pickley并将其发送到每个进程,在本例中,我要求在每个进程中分别进行设置 因此,我可以这样做来设置每个流程: class MyProcess(mp.Proce
def fun(x):
y = setup()
return y.f(x)
pool = mp.Pool(4)
pool.map(fun, my_list)
但是,setup()
非常昂贵,因此我只想在每个过程中执行一次,而不是在我的列表中的每个项目执行一次
我也不想pickley
并将其发送到每个进程,在本例中,我要求在每个进程中分别进行设置
因此,我可以这样做来设置每个流程:
class MyProcess(mp.Process):
def __init__(self):
self.y = setup()
def fun(x):
return self.y.f(x)
workers = [MyProcess() for _ in range(4)]
我现在有没有办法像使用水池一样使用工人?i、 e.将一些工作人员的worker.fun
映射到my_列表中的每个项目
?理想情况下,我想要这样的东西:
对于workers.imap\u无序的结果(MyProcess.fun,my\u列表):
#做点什么
我怀疑使用队列的解决方案也会起作用,但我不完全确定如何实现这一点。我觉得您仍然可以使用池:
def fun(x)
y = setup()
return [y.f(item) for item in x]
processes = 4
newlist = []
for i in range(processes):
mylist[i * len(mylist)//4: (i + 1) * len(mylist)//4]
newlist.append(mylist)
pool = mp.Pool(4)
pool.map(fun, new_list)
拆分列表会有开销,但这是我能想到的减少调用setup次数的最简单解决方案
注意:此版本代码中的x是一个值列表,而不是单个值。a已经支持在启动时自定义每个进程。定义创建y
并使其可访问的池进程的初始化器:
def init_process():
global y # make y accessible to everything
y = setup() # ... and initialise it
def fun(x):
# use already initialised y
return y.f(x)
pool = mp.Pool(4, initializer=init_process)
pool.map(fun, my_list)
要在创建池中的进程时对其进行初始化,可以使用池的初始值设定项
和初始化参数
举例说明该方法:
import multiprocessing as mp
init_obj = {}
def setup(a):
global init_obj
init_obj = {"one": a}
def fun(x):
y = init_obj
print(y)
pool = mp.Pool(None, initializer=setup, initargs=(1,))
pool.map(fun, [0, 1, 2])
每个进程都在自己的内存空间(包括主内存空间)中运行,因此您的类将无法工作,因为初始化没有在将使用其fun()
成员的进程的内存=空间中完成。您可以使用。您的问题是“如何将进程列表用作池”,还是“如何初始化池中的进程”?@mistermiagi任何一个都可以解决我的问题这可能会起作用(即使我不喜欢全局变量)。例如,如果我以后想在每个进程的状态中添加另一个变量,有没有办法?初始值设定项可以运行任意代码,因此可以定义任意多个变量。对不起,我的意思是在以后运行另一个初始值设定项来更新第二个变量z,例如在运行pool.map()之后
一次。这可能吗?@mxbi那不是初始值设定项。这可能是因为您正在寻找错误的机制,希望使用缓存/备忘录来避免重新运行函数。当然,只需使用另一个适用于第二个任务的初始化器打开一个新池就足够了。不,我想定期从主进程向工作进程发送新状态(在map
调用之间)-不能对工作进程计算此状态。但我想我可以销毁它们并创建新的(以性能为代价)这并不理想,因为我们失去了池的“负载平衡”行为,但它会起作用。它也不适用于使用例如imap\u unordered
迭代map的输出,但我在问题中没有指定这一点