簡體   English   中英

多重處理:使用多個while true的queue.get()工作者時的響應度與CPU負載

[英]Multiprocessing: Responsiveness vs CPU load when using multiple while true queue.get() workers

我寫了一些While True工作程序示例,它們從隊列中獲取數據。 原則上,生產者的行為應類似於以下內容,但實際上,它是來自多個ssl套接字供稿的數據,因此此處的生產者用於模擬目的。

在我的情況下,毫秒的分數很重要,而且我在如何確定以下替代方法(或某些其他替代方法)中最好的方法上很掙扎。 我了解到時間分割可能會影響響應速度。 當我嘗試運行下面的代碼時,涉及CPU負載的所有示例均運行良好,除了替代5占用了我100%的CPU。

到目前為止,我的結論是,鑒於非阻塞式.get()循環的睡眠時間非常短,阻​​塞式.get()所消耗的CPU比非阻塞式.get()少。

我的目標是實現將占用很少的CPU時間並響應新更新的代碼。 即,我希望其中一名工人在新物品到達隊列后的0.1毫秒內完成工作。

適用於Windows 7的以Python 2.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)

您最有可能通過刪除任何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還需要修改打印機以使其printerq

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM