Python多处理数据输出错误

时间:2016-10-18 04:35:53

标签: python numpy multiprocessing

我在Python中尝试多处理。我已经编写了一些代码来执行向量添加,但无法从函数中获取输出。这意味着,输出Z打印出0而不是2。

from multiprocessing import Process
import numpy as np

numThreads = 16
num = 16

numIter = num/numThreads

X = np.ones((num, 1))
Y = np.ones((num, 1))
Z = np.zeros((num, 1))

def add(X,Y,Z,j):
    Z[j] = X[j] + Y[j]

if __name__ == '__main__':
  jobs = []
  for i in range(numThreads):
    p = Process(target=add, args=(X, Y, Z, i,))
    jobs.append(p)

  for i in range(numThreads):
    jobs[i].start()

  for i in range(numThreads):
    jobs[i].join()

  print Z[0]

编辑:提出了关于clocker的建议,并将我的代码更改为:

import multiprocessing
import numpy as np

numThreads = 16
numRows = 32000
numCols = 2
numOut = 3

stride = numRows / numThreads

X = np.ones((numRows, numCols))
W = np.ones((numCols, numOut))
B = np.ones((numRows, numOut))
Y = np.ones((numRows, numOut))

def conv(idx):
  Y[idx*stride:idx*stride+stride] = X[idx*stride:idx*stride+stride].dot(W) + B[idx*stride:idx*stride+stride]

if __name__=='__main__':
  pool = multiprocessing.Pool(numThreads)
  pool.map(conv, range(numThreads))
  print Y

输出是Y而不是Saxp。

1 个答案:

答案 0 :(得分:0)

你的最后一行print Z[0]返回[0]而不是[2]的原因是每个进程都创建一个Z的独立副本(或者可能是Z[j] - 不完全确定)在修改它之前。无论哪种方式,单独的流程运行将保证您的原始版本不会改变。

如果您使用threading module而不是最后一行确实会按预期返回[2],但这不是多处理。

因此,您可能希望使用multiprocessing.Pool。纯粹为了说明而进行实验,可以做到以下几点:

In [40]: pool = multiprocessing.Pool()
In [41]: def add_func(j):
   ....:     return X[j] + Y[j]
In [42]: pool = multiprocessing.Pool(numThreads)
In [43]: pool.map(add_func, range(numThreads))
Out[43]: 
[array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.]),
 array([ 2.])]

玩得开心!

对于你的问题的第二部分,问题是conv()函数不返回任何值。当进程池获取X,B和W的副本以从中提取值时,conv()内的Y对于每个启动的进程是本地的。要获得Y的新计算值,您可以使用以下内容:

def conv(idx):
    Ylocal_section = X[idx*stride:idx*stride+stride].dot(W) +  B[idx*stride:idx*stride+stride]
    return Ylocal_section 

results = pool.map(conv, range(numThreads)) # then apply each result to Y
for idx in range(numThreads):
    Y[idx*stride:idx*stride+stride] = results[idx] 

并行性可以非常快速地复杂化,此时我将评估可以执行快速2D卷积的现有库。 numpy和scipy库可以超级高效,可以更好地满足您的需求。