numpy和multiprocessing.process的怪异行为

时间:2018-08-14 18:40:09

标签: python-2.7 numpy multiple-processes

很抱歉,我的代码太长了,我试图使其尽可能简单并且可重现。

简而言之,此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"行。够奇怪的是,如果我将arange10001更改为1001,它将结束。发生什么事了?

3 个答案:

答案 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()方法来避免这种行为。)

     

这意味着,每当您使用队列时,都需要确保在加入该进程之前,将最终删除队列中已放置的所有项目。否则,您无法确定将项目放入队列的进程将终止。还请记住,非守护进程将自动加入。