在Python中优化多处理(跟进:使用队列)

时间:2014-02-24 04:45:17

标签: python multiprocessing

这是this的后续问题。用户将建议使用队列,我试图在下面实现该解决方案。该解决方案在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()

1 个答案:

答案 0 :(得分:1)

你将'STOP'毒药放入你的uncrunched_queue(你应该),并让你的生产者相应关闭;另一方面,您的消费者只检查被挤压队列的空虚:

while not crunched_queue.empty():

(这个 at all 取决于竞争条件,顺便说一句,这不好)

当你开始向你的bazinga生产者投掷非平凡的工作单位时,他们需要更长的时间。如果所有这些都花了足够长的时间,你的crunched_queue会干涸,而你的消费者就会死亡。我想你可能会错误地识别正在发生的事情 - 你的程序没有“挂起”,它只是停止输出东西,因为你的消费者已经死了。

您需要实施更智能的方法来关闭您的消费者。要么查找 n 毒丸,其中 n 是生产者的数量(因此每个人在关闭时每个人在crunched_queue中抛出一个),或者使用某些东西就像一个Semaphore计算每个现场制作人一样,当一个人关闭时就算下来。