我正在使用以下模式进行多处理:
for item in data:
inQ.put(item)
for i in xrange(nProcesses):
inQ.put('STOP')
multiprocessing.Process(target=worker, args=(inQ, outQ)).start()
inQ.join()
outQ.put('STOP')
for result in iter(outQ.get, 'STOP'):
# save result
哪个工作正常。但是如果我通过outQ
发送一个numpy数组,则'STOP'
不会在outQ
的末尾结束,导致我的结果提取循环提前终止。
以下是一些重现bahaviour的代码。
import multiprocessing
import numpy as np
def worker(inQ, outQ):
for i in iter(inQ.get, 'STOP'):
result = np.random.rand(1,100)
outQ.put(result)
inQ.task_done()
inQ.task_done() # for the 'STOP'
def main():
nProcesses = 8
data = range(1000)
inQ = multiprocessing.JoinableQueue()
outQ = multiprocessing.Queue()
for item in data:
inQ.put(item)
for i in xrange(nProcesses):
inQ.put('STOP')
multiprocessing.Process(target=worker, args=(inQ, outQ)).start()
inQ.join()
print outQ.qsize()
outQ.put('STOP')
cnt = 0
for result in iter(outQ.get, 'STOP'):
cnt += 1
print "got %d items" % cnt
print outQ.qsize()
if __name__ == '__main__':
main()
如果您使用result = np.random.rand(1,100)
之类的内容替换result = i*i
,则代码可按预期工作。
这里发生了什么?我在这里做了一些根本错误的事吗?我希望outQ.put()
之后inQ.join()
能够做我想要的事情,因为join()
阻止所有进程完成所有put()
。
为我工作的解决方法是使用while outQ.qsize() > 0
进行结果获取循环,这可以找到。但我读qsize()
并不可靠。在不同的流程运行时,它是否只是不可靠?在完成qsize()
之后,是否可以让我依赖inQ.join()
?
我希望有些人建议使用multiprocessing.Pool.map()
,但是当使用numpy数组(ndarrays)时,我会遇到pickle错误。
感谢您一看!
答案 0 :(得分:1)
numpy数组使用丰富的比较。所以a =='STOP'返回一个numpy数组,而不是bool,并且numpy数组不能被强制转换为bool。在封面下,iter(outQ.get,'STOP')正在进行该比较,并且可能在尝试将结果转换为bool为False时处理异常。你必须做一个手动while循环,从队列中提取项目,检查是否isinstance(item,basestring),然后再将它与'STOP'进行比较。
while True:
item = outQ.get()
if isinstance(item, basestring) and item == 'STOP':
break
cnt += 1
检查qsize()可能也会正常工作,因为在加入输入队列后没有其他进程添加到队列中。
答案 1 :(得分:1)
既然你知道outQ
会有多少项,那么另一种解决办法就是明确地等待这些项目:
import multiprocessing as mp
import numpy as np
import Queue
N=100
def worker(inQ, outQ):
while True:
i,item=inQ.get()
result = np.random.rand(1,N)
outQ.put((i,result))
inQ.task_done()
def main():
nProcesses = 8
data = range(N)
inQ = mp.JoinableQueue()
outQ = mp.Queue()
for i,item in enumerate(data):
inQ.put((i,item))
for i in xrange(nProcesses):
proc=mp.Process(target=worker, args=[inQ, outQ])
proc.daemon=True
proc.start()
inQ.join()
cnt=0
for _ in range(N):
result=outQ.get()
print(result)
cnt+=1
print(cnt)
print('got {c} items'.format(c=cnt))
if __name__ == '__main__':
main()