Python多处理池在for循环中返回相同的输出

时间:2018-07-02 07:19:48

标签: python for-loop multiprocessing spyder pool

我正在Windows 10计算机上通过Spyder 3.6.5在Python 3.6中使用multiprocessing.Pool。目的是通过导入多个输入来从简单的平方函数中获得输出(在此示例中,针对实际问题仅包含4个值)。下面的代码可以正常工作:

import numpy as np
import multiprocessing

from multiprocessing import Pool

data=[]
data.append(np.array([1,2]))
data.append(np.array([4,5]))

Output=np.zeros((2,2))


for i in range (0,2):

    data1=data[i]

    def square(x):
        return x*x

    if __name__ == '__main__':
        __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"
        with Pool(multiprocessing.cpu_count()) as p:
            output = p.map(square, data1, chunksize=10)
            p.close()
            output=np.asarray(output)
            Output[i]=output

当我想将输入平方函数值(x)指定为:

def square(ii):
    x=data1[ii]
    return x*x

for循环运行两次(由于'for i在(0,2)范围内'),但是p.map的结果在每次运行中都相同,并且等于第二次运行,即不是输出= np.array([[1,4],[16,25]])我得到Output = np.array([[16,25],[16,25]])。似乎for循环在i = 1的情况下运行了两次,而不是在第一个循环i = 0和在第二个循环i = 1中运行。

关于我在做什么错的任何想法?

1 个答案:

答案 0 :(得分:0)

Python中的闭包不会复制它们关闭的变量的值。他们只是引用该范围。在您的第二次尝试中,square函数正在访问data1,就好像两次迭代中的值都是不同的一样,但实际上它是对相同基础变量的引用。在多处理模块启动一个新进程并调用square时,该变量已经更改。

例如尝试一下:

res = []
for i in range(5):
    def square():
        return i * i
    res.append(square)


print([f() for f in res])

对于解决方案,您可以在每次迭代中手动创建一个具有适当值的新范围。

函数调用会创建一个新的作用域,因此您可以在循环外定义这样的辅助函数

def square_creater(data1):
    def square(ii):
        x = data1[ii]
        return x * x
    return square

然后在每次迭代中使用

square = square_creater(data1)

这应该有效。