我试图在多个实例上并行调用相同的方法,其中实例引用同一个对象。
对此混淆声明感到抱歉。
具体来说,我想将以下for循环更改为并行执行:
for i in range(len(instances)):#instances is a list of instances
instances[i].do_some_computation_over_a_dataset()
有可能吗?
请注意未来的读者:
上面的代码不是迭代Python中的一组实例的方法。这是如何以顺序(即非并行)方式迭代:
for i in instances:
i.do_some_computation_over_a_dataset()
答案 0 :(得分:2)
好的,我们来做吧。首先是代码(multiprocessing docs):
In [1]: from multiprocessing import Process
In [2]: def f():
...: print(1)
...: for i in range(100):
...: # do something
...: pass
...:
In [3]: p1 = Process(target=f)
In [4]: p1.start()
1
In [5]: p2 = Process(target=f)
In [6]: p2.start()
1
In [7]: import time
In [8]: def f():
...: for i in range(100):
...: print(i)
...: # do something
...: time.sleep(1)
...: pass
...:
In [9]: p1 = Process(target=f)
In [9]: p1 = Process(target=f)
In [10]: p1.start()
0
In [11]: p2 1
= Process(target=f)2
3
4
5
In [11]: p2 = Process(target=f)
In [12]: 6
p2.7
start8
In [12]: p2.start()
0
In [13]: 9
这是一个如何并行调用函数的示例。从In [10]: p1.start()
开始,您可以看到输出混乱,因为当我们运行程序p2时,程序p1并行运行。
在Python脚本中运行程序时,您希望确保脚本仅在所有程序成功执行后结束。你可以通过
来做到这一点def multi_process(instance_params, *funcs):
process = []
for f in funcs:
prog = Process(target=f, args=instance_params)
prog.start()
process.append(prog)
for p in process:
p.join()
multi_process(params, f, f)
由于GIL,Python没有C ++或Java那样的多线程支持。 Read about it here。虽然如果你的程序执行更多I / O操作然后CPU密集型任务,那么你可以使用多线程。为了执行CPU密集型任务,建议使用多处理。
评论@ytutow询问工作人员和进程之间有什么区别。来自Pymotw:
Pool类可用于管理固定数量的worker 可以分解要完成的工作的简单案例 独立地在工人之间分配。
收集作业的返回值并将其作为列表返回。
池参数包括进程数和函数 在启动任务过程时运行(每个孩子调用一次)。
您可以将游泳池用作:
def your_instance_method(instance):
instances.do_some_computation_over_a_dataset()
with Pool(3) as p:
instances = [insatnce_1, instance_2, instance_3]
print(p.map(your_instance_method, instances))
关于正确数量的工人,它的通用建议是拥有2 * cpu_cores工人数。
答案 1 :(得分:2)
此代码似乎显示了for
循环和Pool
之间的区别,在不同的实例上调用方法:
from multiprocessing import Pool
instances = ['a','ab','abc','abcd']
def calc_stuff(i):
return len(i)
if __name__ == '__main__':
print('One at a time')
for i in instances:
print(len(i))
print('Use Pool')
with Pool(4) as pool:
print(pool.map(calc_stuff, instances))
请注意使用if __name__ == '__main':
这将每个进程分开。
输出:
One at a time
1
2
3
4
Use Pool
[1, 2, 3, 4]