Python多处理队列使代码因大数据而挂起

多迪雷

我正在使用python的多处理程序来分析一些大文本。经过几天的努力弄清楚为什么我的代码被挂起(即进程没有结束),我能够使用以下简单的代码重新创建问题:

import multiprocessing as mp

for y in range(65500, 65600):
    print(y)

    def func(output):

         output.put("a"*y)

    if __name__ == "__main__":

        output = mp.Queue()

        process = mp.Process(target = func, args = (output,))

        process.start()

        process.join()

如您所见,如果要放入队列中的项目太大,则过程将挂起。它不会冻结,如果我在output.put()运行后编写更多代码,则该过程永远不会停止。

当字符串达到65500个字符时,就会开始发生这种情况,具体取决于您的解释器,它可能会有所不同。

我知道mp.Queue有一个maxsize参数,但是进行一些搜索后发现,它与队列中项目数的大小有关,而不是项目本身的大小。

有没有解决的办法?我需要在原始代码中放入Queue的数据非常大...

GPhilo

您的队列已满,没有任何消费者可以清空它。

从定义Queue.put

如果可选参数块为True(默认值),并且超时为无(默认值),则如有必要,请阻塞,直到有可用的插槽可用。

假设生产者和使用者之间没有死锁(并且假设您的原始代码确实有使用者,因为您的示例没有),那么最终应该解除生产者并终止生产者。检查您消费者的代码(或将其添加到问题中,以便我们查看)


更新资料

这不是问题,因为没有给队列一个maxsize,所以放置应该成功,直到用完内存。

这不是队列的行为。如该票证中所述,此处阻塞的部分不是队列本身,而是底层管道。从链接的资源(“ []”之间的插入是我的):

队列的工作方式如下:-调用queue.put(data)时,数据被添加到双端队列,该双端队列可以永远增长和收缩-然后线程从双端队列弹出元素,并将其发送出去,以便其他进程可以通过管道或Unix套接字(通过套接字对创建)接收它们。但是,这很重要,管道和unix套接字的容量都是有限的(以前是4k-页面大小-在较旧的Linux内核上用于管道,现在是64k,unix套接字在64k-120k之间,具体取决于可调systcls) 。-当您执行queue.get()时,您只需在管道/插座上进行读取

[..]当大小[变得太大]时,写线程在写syscall上阻塞。而且由于联接是在出队项[注:这是您的process.join]之前执行的,所以您就陷入僵局,因为联接等待发送线程完成,并且由于管道/套接字已满,写入无法完成!如果您在等待提交程序之前将项目出队,则一切正常。


更新2

我明白。但是我实际上没有消费者(如果这就是我的想法),我只会在流程完成将其放入队列后才从队列中获取结果。

是的,这就是问题所在。multiprocessing.Queue不是一个储存容器。您应该专门将其用于在“生产者”(生成进入队列的数据的过程)和“消费者”(“使用”该数据的过程)之间传递数据。如您所知,将数据留在这里是个坏主意。

如果我什至不能先把物品放到队列里怎么办?

putget避免了在数据填满管道时将数据放在一起的问题,因此您只需要在“主”流程中为循环中的get项目设置一个循环,例如,将其追加到列表中。该列表位于主进程的内存空间中,不会阻塞管道。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章