我对python Multiprocessing.pool有一个快速的问题。这是我的代码:
import multiprocessing as mp
info =999
def func(x):
global info
print info
return x**3
pool = mp.Pool()
for i in range(2):
print "Iteration: ", i
results = pool.map(func, range(1,10))
print "Value of info", info
info += 1
print results
print "Iteration", i, "End"
print
输出看起来像这样:
999
999
999
999
999
999
999
999
999
999
999
999
999
999
999
999
999
999
Iteration: 0
Value of info 999
[1, 8, 27, 64, 125, 216, 343, 512, 729]
Iteration 0 End
Iteration: 1
Value of info 1000
[1, 8, 27, 64, 125, 216, 343, 512, 729]
Iteration 1 End
我想知道为什么在第二次迭代中再次打印999,而不是1000。如何更新全局变量信息,以便在第二次迭代中打印1000?非常感谢!
最佳答案
评论已经解释了一下。我想我会解释更多。
使用multiprocessing
模块时,它将在pool
中按请求的进程数创建新进程。默认值由multiprocessing.cpu_count()
计算。
假设您编写的脚本是A.py
,它创建了进程A
。当A
创建新进程时,它们称为A
的子进程。这些子进程的全局变量以A
开始。
但是,每个子进程都有各自的作用域,因此在一个子进程中更改变量info
不会影响其他子进程中的info
值。并且它当然不会影响父进程A
中的值。
一个简单的解决方案是指示每个子进程向父进程info
报告所需的A
更改。也就是说,map
中的每个子进程都应返回-1
作为结果,而父进程A
则将更新汇总在其自己的范围内。在分布式计算中,这称为参数服务器设计。
在理想的世界中,您真正想要的是线程,它共享作用域和内存。但是,由于Python
,Global Interpreter Lock
线程可能变得非常复杂。如果您有兴趣,可以对此进行一些Google搜索。
我误读了您的代码。在我凌晨2点时,我读到了孩子们对info
的修改以及父母对他的打印。事实恰恰相反。
您正确的一点是,修改不跨进程共享。如果您在子进程中使用global
访问info
,则子进程将不知道更改,因为该功能在模块创建时为pickled
。您可以在http://grahamstratton.org/straightornamental/entries/multiprocessing继续阅读
您需要将动态info
作为函数的参数发送给它,如下所示:
import multiprocessing as mp
def dual_input(t):
info, x = t
print info
return x**3
def main():
info =999
pool = mp.Pool(2)
for i in range(2):
print "Iteration: ", i
results = pool.map(dual_input, zip([info]*9, range(1,10)))
print "Value of info", info
info += 1
print results
print "Iteration", i, "End"
print
if __name__ == '__main__': main()
上面的代码打印:
Iteration: 0
999
999
999
999
999
999
999
999
999
Value of info 999
[1, 8, 27, 64, 125, 216, 343, 512, 729]
Iteration 0 End
Iteration: 1
1000
1000
1000
1000
1000
1000
1000
1000
1000
Value of info 1000
[1, 8, 27, 64, 125, 216, 343, 512, 729]
Iteration 1 End
关于python - 循环使用multiprocessing.pool和更新目标函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47402616/