很抱歉,我的代码太长了,我试图使其尽可能简单并且可重现。
简而言之,此python脚本启动了四个进程,这些进程将数字随机分配到列表中。然后,将结果添加到multiprocessing.Queue()
。
import random
import multiprocessing
import numpy
import sys
def work(subarray, queue):
result = [numpy.array([], dtype=numpy.uint64) for i in range (0, 4)]
for element in numpy.nditer(subarray):
index = random.randint(0, 3)
result[index] = numpy.append(result[index], element)
queue.put(result)
print "after the queue.put"
jobs = []
queue = multiprocessing.Queue()
subarray = numpy.array_split(numpy.arange(1, 10001, dtype=numpy.uint64), 4)
for i in range(0, 4):
process = multiprocessing.Process(target=work, args=(subarray[i], queue))
jobs.append(process)
process.start()
for j in jobs:
j.join()
print "the end"
所有进程都运行print "after the queue.put"
行。但是,它并没有到达print "the end"
行。够奇怪的是,如果我将arange
从10001
更改为1001
,它将结束。发生什么事了?
答案 0 :(得分:1)
我将把我的评论扩展为一个简短的答案。由于我也不了解这种怪异的行为,因此这只是一种解决方法。
第一个观察结果是,如果将queue.put行注释掉,代码将运行到末尾,因此它一定是与队列有关的问题。结果实际上已添加到队列中,因此问题必须出在队列和联接之间。
以下代码按预期工作
import random
import multiprocessing
import numpy
import sys
import time
def work(subarray, queue):
result = [numpy.array([], dtype=numpy.uint64) for i in range (4)]
for element in numpy.nditer(subarray):
index = random.randint(0, 3)
result[index] = numpy.append(result[index], element)
queue.put(result)
print("after the queue.put")
jobs = []
queue = multiprocessing.Queue()
subarray = numpy.array_split(numpy.arange(1, 15001, dtype=numpy.uint64), 4)
for i in range(4):
process = multiprocessing.Process(target=work, args=(subarray[i], queue))
jobs.append(process)
process.start()
res = []
while len(res)<4:
res.append(queue.get())
print("the end")
答案 1 :(得分:0)
大多数子进程在调用时阻塞。 multiprocessing queue put
根据需要阻止,直到有可用的插槽为止。
可以通过在连接之前添加对queue.get()的调用来避免这种情况。
此外,在多处理代码中,请通过以下步骤隔离父进程:
if __name__ == '__main__':
# main code here
Compulsory usage of if name==“main” in windows while using multiprocessing
答案 2 :(得分:0)
这是原因:
Joining processes that use queues
请记住,将项目放入队列的进程将在终止之前等待,直到所有缓冲的项目由“ feeder”线程馈送到基础管道为止。 (子进程可以调用队列的cancel_join_thread()方法来避免这种行为。)
这意味着,每当您使用队列时,都需要确保在加入该进程之前,将最终删除队列中已放置的所有项目。否则,您无法确定将项目放入队列的进程将终止。还请记住,非守护进程将自动加入。