Python 使用多处理混淆修改传入对象

Python 使用多处理混淆修改传入对象,python,multiprocessing,python-multithreading,Python,Multiprocessing,Python Multithreading,我编写了一个函数来修改传入的字典。然而,当我使用多处理模块并行化代码时,它表现出与串行运行时不同的行为。字典没有修改 下面是我的问题的一个玩具例子。使用map_async运行时不会修改字典,但在for循环中运行时会修改字典。谢谢你澄清我的困惑 #!/usr/bin/env python from multiprocessing import Pool def main1(x): x['a'] = 1 print x return 1 def main2(x): x['b'

我编写了一个函数来修改传入的字典。然而,当我使用多处理模块并行化代码时,它表现出与串行运行时不同的行为。字典没有修改

下面是我的问题的一个玩具例子。使用map_async运行时不会修改字典,但在for循环中运行时会修改字典。谢谢你澄清我的困惑

#!/usr/bin/env python

from multiprocessing import Pool

def main1(x):
  x['a'] = 1
  print x

  return 1

def main2(x):
  x['b'] = 2
  print x

p = Pool(2)
d = {1:{}, 2:{}}
r = p.map_async(main1, d.values())
print r.get()
print "main1", d

for x in d.values():
  main2(x)

print "main2", d

您正在
main1
中更改可变参数。但这发生在不同于运行池的进程中。他们不共享数据


运行
map\u async
时,python将每次迭代的数据复制到工作进程,然后工作进程执行该函数,收集返回值并将其传递回运行
map\u async
的进程。它不会传回任何修改过的参数。

您正在
main1
中更改可变参数。但这发生在不同于运行池的进程中。他们不共享数据

运行
map\u async
时,python将每次迭代的数据复制到工作进程,然后工作进程执行该函数,收集返回值并将其传递回运行
map\u async
的进程。它不会传回任何修改过的参数。

r=p.map\u async(main1,d.values())
执行以下操作:

1)评估
d.values()
-这就是
[{},{}]

2)对池中的工作进程中该列表中的每个项目执行
main1(项目)
3)将这些调用的结果收集到一个列表中-
[1,1]
-因为这就是
main1
返回的结果
4)将该列表分配给
r

因此,它与内置函数的功能完全相同,但采用并行方式

这意味着,您的dict
d
从未进入任何工作进程,因为它不是传递给
map\u async
的对
d
的引用,因此
main1

即使你要传递一个对
d
的引用,由于@Roland Smith解释的原因,它也不起作用

重点是:你不应该首先修改字典。在传统编程中,函数修改其参数甚至不是很好的风格,即使它们可以。对于并行编程来说,遵循函数式编程风格是绝对重要的,在本文中,函数式编程风格意味着:

函数应该对其输入进行计算,并返回一个进一步处理的结果

函数mapreduce在函数式编程中非常常见,它们结合在一起形成了非常适合分布式计算的模式。摘自维基百科关于:

“映射”步骤:主节点接收输入,将其分成更小的部分 子问题,并将它们分发到工作节点。工作节点可以是 依次执行此操作,生成一个多级树结构。这个 worker节点处理较小的问题,并将答案返回 到其主节点

“减少”步骤:然后主节点收集所有问题的答案 子问题,并以某种方式将它们组合起来形成输出– 它最初试图解决的问题的答案

因此,为了有效地并行化您的程序,可以尝试从这些函数的角度来思考您的问题

有关一个非常具体的示例,请参阅IEEE Spectrum中的文章。它描述了一种可以用map/reduce轻松实现的方法。

r=p.map\u async(main1,d.values())
执行以下操作:

1)评估
d.values()
-这就是
[{},{}]

2)对池中的工作进程中该列表中的每个项目执行
main1(项目)
3)将这些调用的结果收集到一个列表中-
[1,1]
-因为这就是
main1
返回的结果
4)将该列表分配给
r

因此,它与内置函数的功能完全相同,但采用并行方式

这意味着,您的dict
d
从未进入任何工作进程,因为它不是传递给
map\u async
的对
d
的引用,因此
main1

即使你要传递一个对
d
的引用,由于@Roland Smith解释的原因,它也不起作用

重点是:你不应该首先修改字典。在传统编程中,函数修改其参数甚至不是很好的风格,即使它们可以。对于并行编程来说,遵循函数式编程风格是绝对重要的,在本文中,函数式编程风格意味着:

函数应该对其输入进行计算,并返回一个进一步处理的结果

函数mapreduce在函数式编程中非常常见,它们结合在一起形成了非常适合分布式计算的模式。摘自维基百科关于:

“映射”步骤:主节点接收输入,将其分成更小的部分 子问题,并将它们分发到工作节点。工作节点可以是 依次执行此操作,生成一个多级树结构。这个 worker节点处理较小的问题,并将答案返回 到其主节点

“减少”步骤:然后主节点收集所有问题的答案 子问题,并以某种方式将它们组合起来形成输出– 它最初试图解决的问题的答案

因此,为了有效地并行化您的程序,可以尝试从这些函数的角度来思考您的问题

对于一个非常具体的