多处理池没有返回值?

时间:2017-12-13 15:46:51

标签: python python-3.x multiprocessing python-multithreading

我正在尝试使用多处理Pool而没有返回值进行并行计算。如果不需要从子进程返回和检索值,则可能会更快。有没有办法做到这一点?

这是一个简单的例子:

from multiprocessing import Pool

def fun(a):
    # do something.. 
    a["1"]=100

a={
   "1":12
   }
multi = [a] * 10
p = Pool(4)
p.map(fun, multi)
data = [a["1"] for a in multi]
print(data)
>>> [12, 12, 12, 12, 12, 12, 12, 12, 12, 12]

[fun(a) for a in multi]
data = [a["1"] for a in multi]
print(data)
>>> [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]

有人知道为什么吗?那是否有解决方案?

1 个答案:

答案 0 :(得分:2)

您的功能fun

def fun(a):
    # do something.. 
    a["1"]=100

更改了可变参数a。但是,当您使用p.map(fun, multi)调用此项时,multi列表中的每个项目都会被腌制,发送到工作进程并在那里发生变异。这不会对调用过程中列表中的原始项产生任何影响。

您可以使用proxy objects创建可在进程之间共享的数据结构,即managers。您必须创建10个共享词典。在您的示例中,您只有一个字典,该列表包含10个对它的引用,data = [a["1"] for a in multi]将始终只包含相同的值,因为a始终是同一个对象。

所以这应该有效:

from multiprocessing import Pool, Manager
import random

def fun(a):
    # to show that the dictionaries are different
    a["1"] = random.random()

if __name__ == '__main__':
    m = Manager()
    p = Pool(4)
    multi = [m.dict() for _ in range(10)]
    p.map(fun, multi)
    data = [a["1"] for a in multi]
    print(data)

请注意,multi = m.list([a] * 10)或类似内容不起作用,因为只会同步列表访问,而不会更新所包含的元素。但是所有这些都会产生额外的IPC开销,如果可以的话,可能会比使用函数的返回值更糟糕。