多处理:使用多个while true queue.get()工作程序时的响应性与CPU负载

时间:2016-11-02 11:26:13

标签: python queue multiprocessing

我写了几个While True worker从队列中获取数据的例子。原则上,生产者应该表现得像下面这样,但实际上它是来自多个ssl套接字源的数据,因此这里的生产者是出于模拟目的。

毫秒级的分数在我的情况下非常重要,我正在努力确定如何确定以下哪种(或其他替代方案)最佳。我知道时间切片会影响响应能力。当我尝试运行下面的代码时,所有示例都适用于CPU负载,除了替代5,它占用了我100%的CPU。

到目前为止,我的结论是阻塞.get()比非阻塞.get()吃的CPU%少,因为非阻塞.get()循环设置得非常短,睡眠很短。

我的目标是实现能够占用CPU时间以及响应新更新的代码。也就是说,我希望其中一名工人在新项目到达队列之后的0.1毫秒内完成工作。

使用Python 2.7 for Windows 7编写的示例代码(请注意,我使用的是24核计算机,因此可能需要调整工作人员数量):

import multiprocessing
import os
import time
import Queue


class MyClass:
    def __init__(self):
        self.the_queue = multiprocessing.Queue()
        self.printerq = multiprocessing.Queue()

    def producer(self):
        i=0
        while True:
            self.the_queue.put(["hello",i],False)
            i=i+1
            time.sleep(1)

    'alternative 1'
    '''
    def worker_main(self):
        while True:
            try:
                item = self.the_queue.get(timeout=0.1)
            except Queue.Empty:
                time.sleep(0.0001) 
            else:
                self.printerq.put([item,os.getpid()],False)
    '''

    'alternative 2'
    '''
    def worker_main(self):
        while True:
            if not self.the_queue.empty():
                item = self.the_queue.get()
                #print os.getpid(), "got", item
                self.printerq.put([item,os.getpid()],False)
            time.sleep(0.0001)
    '''

    'alternative 3'

    def worker_main(self):
        while True:
            item = self.the_queue.get()
            self.printerq.put([item,os.getpid()],False)

    'alternative 4'
    '''
    def worker_main(self):
        while True:
            item = self.the_queue.get()
            self.printerq.put([item,os.getpid()],False)
            time.sleep(0.0001)
    '''

    'alternative 5 eats CPU 100%'
    '''
    def worker_main(self):
        while True:
            try:
                item = self.the_queue.get(False)
            except Queue.Empty:
                time.sleep(0.0001)
            else:
                self.printerq.put([item,os.getpid()],False)
                time.sleep(0.0001)
    '''

    def printer(self):
        while True:
            stuff=self.printerq.get()
            print stuff


if __name__=='__main__':
    mc=MyClass()

    process_printer = multiprocessing.Process(target=mc.printer, args=())
    process_printer.start() 

    for i in range(100):
        process_window = multiprocessing.Process(target=mc.worker_main, args=())
        process_window.start()
        time.sleep(0.1)

    for i in range(100):
        process_producer = multiprocessing.Process(target=mc.producer, args=())
        process_producer.start() 
        time.sleep(0.1)

1 个答案:

答案 0 :(得分:0)

通过删除任何time.sleep()来电,您最有可能获得最佳性能。我建议使用繁忙等待的queue.get()并使用kill标志来结束进程。你的工作人员应该看起来像这样:

def worker_main(self):
    while True:
        item = self.the_queue.get()
        # Checks for kill flag
        if item == None:
            break 
        self.printerq.put([item,os.getpid()],False)

此方法要求您的制作人将None放入self.the_queue。但是因为你有多个生产者,你可能想修改工人,使他们从每个生产者那里收到一个杀戮标志。类似的东西:

def worker_main(self):
    kill_flags = 0        
    # Make sure to pass in num_producers
    while kill_flags < num_producers:
        item = self.the_queue.get()
        # Checks for kill flag
        if item == None:
            kill_flag += 1
            continue 
        self.printerq.put([item,os.getpid()],False)

就你的制作人而言,类似的方法在完成制作时会起作用:

def producer(self):
    i=0
    while (some_condition_to_stop_producing):
        self.the_queue.put(["hello",i],False)
        i=i+1
        time.sleep(1)
    # Pass in the number of workers
    for i in range(num_workers):
        self.the_queue.put(None)

请勿忘记,当您完成将内容放入printerq后,您还需要修改打印机。