在Python中优化多处理(后续:使用队列)

在Python中优化多处理(后续:使用队列),python,multiprocessing,Python,Multiprocessing,这是我们的后续问题。用户将建议使用队列,我尝试实现下面的解决方案。该解决方案在j=1000时运行良好,但是,当我尝试扩展到更大的数字时,它挂起。我被困在这里,无法确定它为什么会挂起来。如有任何建议,将不胜感激。此外,代码开始变得丑陋,因为我一直在搞乱它,我为所有嵌套函数道歉 def run4(j): """ a multicore approach using queues """ from multiprocessing import Process, Queu

这是我们的后续问题。用户将建议使用队列,我尝试实现下面的解决方案。该解决方案在j=1000时运行良好,但是,当我尝试扩展到更大的数字时,它挂起。我被困在这里,无法确定它为什么会挂起来。如有任何建议,将不胜感激。此外,代码开始变得丑陋,因为我一直在搞乱它,我为所有嵌套函数道歉

def run4(j):
    """
    a multicore approach using queues
    """
    from multiprocessing import Process, Queue, cpu_count
    import os

    def bazinga(uncrunched_queue, crunched_queue):
        """
        Pulls the next item off queue, generates its collatz
        length and 
        """
        num = uncrunched_queue.get()
        while num != 'STOP': #Signal that there are no more numbers
            length = len(generateChain(num, []) )
            crunched_queue.put([num , length])
            num = uncrunched_queue.get()

    def consumer(crunched_queue):
        """
        A process to pull data off the queue and evaluate it
        """
        maxChain = 0
        biggest = 0
        while not crunched_queue.empty():
            a, b = crunched_queue.get()
            if b > maxChain:
                biggest = a
                maxChain = b
        print('%d has a chain of length %d' % (biggest, maxChain))

    uncrunched_queue = Queue()
    crunched_queue = Queue()
    numProcs = cpu_count()

    for i in range(1, j): #Load up the queue with our numbers
        uncrunched_queue.put(i)
    for i in range(numProcs): #put sufficient stops at the end of the queue
        uncrunched_queue.put('STOP')

    ps = []
    for i in range(numProcs):
        p = Process(target=bazinga, args=(uncrunched_queue, crunched_queue))
        p.start()
        ps.append(p)

    p = Process(target=consumer, args=(crunched_queue, ))
    p.start()
    ps.append(p)

    for p in ps: p.join()

您正在将
'STOP'
毒药放入您的
未运行的队列中
(您应该这样做),并相应地关闭您的生产商;另一方面,您的消费者只检查拥挤队列的空性:

while not crunched_queue.empty():
(这完全取决于比赛条件,顺便说一句,这并不好)

当你开始向你的
bazinga
制作人抛出非琐碎的工作单元时,它们需要更长的时间。如果所有这些花费足够长的时间,你的
拥挤的队列就会干涸,你的消费者就会死亡。我认为你可能误判了正在发生的事情——你的程序没有“挂起”,它只是停止输出东西,因为你的消费者已经死了


您需要实施更智能的方法来关闭您的消费者。或者寻找n个毒药丸,其中n是生产商的数量(当他们关闭时,每个生产商相应地将一个毒药丸扔进
crunched_队列中),或者使用类似于
的信号灯,对每个活着的生产商计数,当一个生产商关闭时计数。

我在bazinga()的末尾添加了以下内容:
crunched_队列。put(['STOP','STOP'])
并且我向消费者添加了一个计数器,以便在收到适当数量的停止后停止。这很好,但是,脚本似乎没有使用多个处理器(在我的活动管理器中只有一个Python进程,而不是numProcs+1)当j>10000时,这会导致运行速度非常慢。我在最初的帖子中将问题分解为处理器之间的块。很好,你知道为什么这篇文章不会这样做吗?