2017-08-09 91 views
4

我有代碼從無限次的時間每秒從7個設備讀取數據。每個循環,都會創建一個啓動7個進程的線程。每個過程完成後,程序等待1秒鐘並重新開始。這是一段代碼:Python:我如何停止使用100%CPU的線程/多處理?

def all_thread(): #function that handels the threading 
    thread = threading.Thread(target=all_process) #prepares a thread for the devices 
    thread.start() #starts a thread for the devices 

def all_process(): #function that prepares and runs processes 
    processes = [] #empty list for the processes to be stored 
    while len(gas_list) > 0: #this gaslist holds the connection information for my devices 
     for sen in gas_list: #for each sen(sensor) in the gas list 
      proc = multiprocessing.Process(target=main_reader, args=(sen, q)) #declaring a process variable that sends the gas object, value and queue information to reading function 
      processes.append(proc) #adding the process to the processes list 
      proc.start() #start the process 
     for sen in processes: #for each sensor in the processes list 
      sen.join() #wait for all the processes to complete before starting again 
     time.sleep(1) #wait one second 

但是,這使用了我的CPU的100%。這是通過線程和多處理設計還是僅僅是錯誤的編碼?有沒有辦法限制CPU使用率?謝謝!

更新:

的意見被提main_reader()功能,所以我會把它進入正題。它所做的就是讀取每個設備,獲取所有數據並將其附加到列表中。然後將列表放入隊列以顯示在tkinter GUI中。

def main_reader(data, q): #this function reads the device which takes less than a second 
    output_list = get_registry(data) #this function takes the device information, reads the registry and returns a list of data 
    q.put(output_list) #put the output list into the queue 
+0

在Python中啓動一個進程意味着啓動一個Python解釋器的新實例,這意味着在你的情況下,你有4-8個核心上運行7個獨立的解釋器(我認爲)。當一個新的解釋器產生時,它會從父進程繼承一堆資源,以便能夠完成它的工作,這意味着產生一個新進程可能非常緩慢且代價高昂。你的進程正在運行一個名爲'main_reader()'的函數,根據名字我假設你正在做的工作主要是IO的東西。你有沒有嘗試開始一堆守護進程而不是所有這些進程? – orangeInk

+0

@orangeInk你是所有的IO。 'main_reader()'讀取設備並準備要顯示的數據。我還沒有玩過守護進程。現在,我正在使用多處理來防止tkinter GUI在設備正在工作時凍結。守護進程也會實現嗎? – GreenSaber

+0

由此看不到main_reader中會發生什麼。這就是你的處理髮生的地方。 All_process在join()中等待。只是一個很小的,可能不相關的東西,你可能想把'processes = []'作爲while循環的第一行。現在這個列表不斷增長,因爲已經加入的進程不會被刪除。迭代之後,您只需將它附加到迭代上。 – Hannu

回答

2

當您在留言狀態時,你的main_reader只需要幾分之一秒的運行,這意味着進程創建開銷可能會導致問題。

以下是multiprocessing.Pool的示例。這會創建一批工作人員並向他們提交任務。進程只啓動一次,如果這意味着無限循環,則不會關閉或加入進程。如果你想關閉你的游泳池,你可以通過加入和關閉游泳池(請參閱文檔)。

from multiprocessing import Pool, Manager 
from time import sleep 
import threading 
from random import random 

gas_list = [1,2,3,4,5,6,7,8,9,10] 

def main_reader(sen, rqu): 
    output = "%d/%f" % (sen, random()) 
    rqu.put(output) 


def all_processes(rq): 
    p = Pool(len(gas_list) + 1) 
    while True: 
     for sen in gas_list: 
      p.apply_async(main_reader, args=(sen, rq)) 

     sleep(1) 

m = Manager() 
q = m.Queue() 
t = threading.Thread(target=all_processes, args=(q,)) 
t.daemon = True 
t.start() 

while True: 
    r = q.get() 
    print r 

如果這不起作用,您需要開始深入挖掘。我首先會將無限循環中的睡眠時間增加到10秒甚至更長。這將允許您監視程序的行爲。如果CPU高峯一會兒,然後穩定下來10秒左右,您知道問題出在您的main_reader中。如果它仍然是100%,你的問題必須在其他地方。

有沒有可能你的問題不在你的程序的這部分?你似乎在一個線程中啓動了這一切,這表明你的主程序正在做其他事情。它可以是這個別的東西,使CPU達到峯值嗎?

+0

我現在要測試這個,我會盡快回復你。我啓動了一個線程來分離Tkinter的主循環和我需要用這些設備完成的工作。 – GreenSaber

+0

然後你可以嘗試它沒有tkinter循環。就在啓動程序的這一部分之後,不要啓動它,並在睡眠中等待(大時間)。你的應用程序沒有太多的功能,但是如果它的表現很好,儘管運行了所有這些後臺任務,那麼你至少知道你的問題不在你的代碼的這一部分。 – Hannu

+0

我可以看到試圖做工作的池,但是沒有任何東西進入'main_reader()'。 – GreenSaber