多处理模块(Python)的map方法中的赋值

时间:2013-01-09 00:24:58

标签: python map multiprocessing

我的问题是关于Python的多处理模块。 在最简单的形式中,我的问题是以下代码的奇怪行为:

import numpy as np
from multiprocessing import Pool

x = np.random.random(100)
y = np.random.random(100)
y2 = y[:]

def I(i):
    y[i] = x[i]

pool = Pool()
pool.map(I,range(100))

执行后,我的希望是y = x。 但是,我们得到y = y2。 (作业不起作用。) 为什么会这样? 计算f(x [i])并将其分配给y [i]的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

如果您考虑Pool用于完成工作的流程之间的同步,您所看到的行为并不令人惊讶。只有I函数的参数和返回值在当前代码中同步,因此xy在调用过程中保留其原始值是有意义的。

我怀疑你当前的代码是一个最小的测试用例,这很麻烦,因为使用Pool.map实际上没有一个有意义的实现将一个数组复制到另一个数组。这是一个简单的解决方案,但我不确定它是否适用于您的实际任务:

import numpy as np
from multiprocessing import Pool

def I(v):
    return v

if __name__ == "__main__":  # this boilerplate is required on on Windows
    x = np.random.random(100)
    y = np.random.random(100)

    pool = Pool()
    y[:] = pool.map(I, x)

    print(x == y) # [True, True, True, ...]

这将x的每个值传递给另一个进程(其中没有任何操作),结果值被传回并分配到y(pool.map返回一个列表)。这很傻。

稍微复杂的方法可能会使用x构造函数中的initializerinitargs参数将Pool复制到工作进程。这是一个例子:

import numpy as np
from multiprocessing import Pool

def I(index):
    return x[index]

def setup(value):
    global x
    x = value

if __name__ == "__main__":
    x = np.random.random(100)
    y = np.random.random(100)

    pool = Pool(initializer=setup, initargs=(x,))
    y[:] = pool.map(I, range(100))

    print(x == y) # [True, True, True, ...]

请注意,x仅以一种方式复制。如果I要修改其值,则不会在进程之间同步更改。

如果您的任务确实需要同步访问源阵列和目标阵列,则可以试用multiprocessing.Array。我对它没有任何直接经验,但应该可以用自身的同步版本替换y。不幸的是,我怀疑同步会降低你的程序速度,所以除非你真的需要,否则不要这样做!