pool.map在对象很大时冻结

Poo*_*kie 6 python-3.x python-multiprocessing

我正在使用pool.map来填充字典 - 称为节点.要明确:在pool.map运行之后填充此字典,因此在进程之间共享变量不是一个问题.函数返回的所有内容以及字典中的所有内容都是可选的.它填充了一个基本上是图形的字典.当我进入填充此图表的1,2,3深度时,程序运行完美无缺.然而在4深:程序似乎没有崩溃,只是冻结.我在映射到的函数中设置了print语句,在运行的最后,它在程序的最顶部打印语句,然后冻结.这是我如何调用pool.map:

    currentNode = startingNode
    nodesPopulated = [currentNode]
    connections = []
    merger = []
    pool = Pool(cpu_count())
    for currentDepth in range(1, depth):
        print('=' * 70)
        print("=  At depth", currentDepth)
        connections = []
        for item in nodesPopulated:
            if item != None:
                if item.isPopulated():
                    connections +=list(item.getConnections().values())
        print("=  Current number of connections:",len(connections))
        print("=  Current number of NodesPopulated in this iteration: ",len(nodesPopulated))
        print("=  Total number of nodes",len(self.nodes.keys()))
        nodesPopulated = pool.map(self.populateTopicNode, connections)
        print('\n=  Successfully populated another round of nodes')
        for node in nodesPopulated:
            if node != None:
                if item.isPopulated():
                    self.nodes[node.getTopic().getName()] = node
                #self.populatedNodes[node.getTopic().getName()] = True;
        print('=  Updated self.nodes\n')

    pool.close()
    pool.join()

    print('\nCount = ',len(list(self.nodes.keys())))
    return
Run Code Online (Sandbox Code Playgroud)

再次,我确保返回到nodesPopulated的所有内容都是可选的.我在我的智慧结束,因为运行这个程序4深度大约需要2小时而没有pool.map它完美无缺,但需要大约6个小时.我不想抛弃多处理,但我无法弄清楚这一点,它需要永远调试.它在冻结之前打印的最后一件事是'D',它位于self.populateTopicNode的顶部.我也认为变得太大的对象(self.nodes和connections)可能就是为什么这会冻结.

注意:我确定这是一个多处理问题,因为我在不使用pool.map的情况下运行了这个确切的代码,并将其替换为for循环,并且运行完成且没有错误.所以有些东西导致pool.map冻结.在第一次引用函数参数时,没有错误消息被挂起.以下是'populateTopicNode'的前几行:

def populateTopicNode(self, node: TopicNode):
    print('D')
    if(node.isPopulated()):
        return None
Run Code Online (Sandbox Code Playgroud)

冻结前在控制台上看到的最后一件事是'D'

编辑:我做了一些测试,为您提供挂起的确切数字: 在此输入图像描述

它使用大约1300 MB的内存挂起.

EDIT2:

好的,所以我发现它正在返回一些不仅仅是随机悬挂的东西.它返回None然后挂起.我不确定为什么因为有很多次它返回None并且工作正常.我还尝试将我的函数包装起来,除了看看是否向父母返回一个异常是吓坏了,这也不是问题.没有异常被捕获,它正在运行到它返回的点.回来后它就会挂起来.

EDIT3:

它在每次迭代时都在相同的位置处中断.我打印它正在处理的当前主题的名称,它总是在同一行的同一点断开然后挂起.我不确定这是否有帮助,但它是附加信息.始终如一地在同一时间打破.

nox*_*fox 6

来自多处理指南。

应尽可能避免在进程之间转移大量数据。

multiprocessing.Pool依靠锁定缓冲区(操作系统管道)在工作人员之间分配任务并检索其结果。如果将大于缓冲区的对象推入管道,则逻辑可能会挂起。

我建议您将作业转储到文件(pickle例如使用)并将文件名发送到子进程。通过这种方式,每个进程都可以独立检索数据。您不仅可以防止您的逻辑卡住,而且您会注意到速度的提高以及管道成为您设计中的严重瓶颈。