您好,登錄后才能下訂單哦!
想要充分利用多核CPU資源,Python中大部分情況下都需要使用多進程,Python中提供了multiprocessing這個包實現多進程。multiprocessing支持子進程、進程間的同步與通信,提供了Process、Queue、Pipe、Lock等組件。
開辟子進程
multiprocessing中提供了Process類來生成進程實例
Process([group [, target [, name [, args [, kwargs]]]]])
先來個小例子:
# -*- coding:utf-8 -*- from multiprocessing import Process, Pool import os import time def run_proc(wTime): n = 0 while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime()) #獲取當前進程號和正在運行是的時間 time.sleep(wTime) #等待(休眠) n += 1 if __name__ == "__main__": p = Process(target=run_proc, args=(2,)) #申請子進程 p.start() #運行進程 print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())
運行結果:
Parent process run. subProcess is 30196
Parent process end,Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:23 2017
subProcess 30196 run, Mon Mar 27 11:20:25 2017
根據運行結果可知,父進程運行結束后子進程仍然還在運行,這可能造成僵尸( zombie)進程。
通常情況下,當子進程終結時,它會通知父進程,清空自己所占據的內存,并在內核里留下自己的退出信息。父進程在得知子進程終結時,會從內核中取出子進程的退出信息。但是,如果父進程早于子進程終結,這可能造成子進程的退出信息滯留在內核中,子進程成為僵尸(zombie)進程。當大量僵尸進程積累時,內存空間會被擠占。
有什么辦法可以避免僵尸進程呢?
這里介紹進程的一個屬性 deamon,當其值為TRUE時,其父進程結束,該進程也直接終止運行(即使還沒運行完)。
所以給上面的程序加上p.deamon = true,看看效果。
# -*- coding:utf-8 -*- from multiprocessing import Process, Pool import os import time def run_proc(wTime): n = 0 while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime()) time.sleep(wTime) n += 1 if __name__ == "__main__": p = Process(target=run_proc, args=(2,)) p.daemon = True #加入daemon p.start() print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())
執行結果:
Parent process run. subProcess is 31856
Parent process end,Mon Mar 27 11:40:10 2017
這是問題又來了,子進程并沒有執行完,這不是所期望的結果。有沒辦法將子進程執行完后才讓父進程結束呢?
這里引入p.join()方法,它使子進程執行結束后,父進程才執行之后的代碼
# -*- coding:utf-8 -*- from multiprocessing import Process, Pool import os import time def run_proc(wTime): n = 0 while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime()) time.sleep(wTime) n += 1 if __name__ == "__main__": p = Process(target=run_proc, args=(2,)) p.daemon = True p.start() p.join() #加入join方法 print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())
執行結果:
subProcess 32076 run, Mon Mar 27 11:46:07 2017
subProcess 32076 run, Mon Mar 27 11:46:09 2017
subProcess 32076 run, Mon Mar 27 11:46:11 2017
Parent process run. subProcess is 32076
Parent process end,Mon Mar 27 11:46:13 2017
這樣所有的進程就能順利的執行了。
將進程定義成類
通過繼承Process類,來自定義進程類,實現run方法。實例p通過調用p.start()時自動調用run方法。
如下:
# -*- coding:utf-8 -*- from multiprocessing import Process, Pool import os import time class Myprocess(Process): def __init__(self, wTime): Process.__init__(self) self.wTime = wTime def run(self): n = 0 while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime()) time.sleep(self.wTime) n += 1 if __name__ == "__main__": p = Myprocess(2) p.daemon = True p.start() #自動調用run方法 p.join() print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())
執行結果和上一個例子相同。
創建多個進程
很多時候系統都需要創建多個進程以提高CPU的利用率,當數量較少時,可以手動生成一個個Process實例。當進程數量很多時,或許可以利用循環,但是這需要程序員手動管理系統中并發進程的數量,有時會很麻煩。這時進程池Pool就可以發揮其功效了。可以通過傳遞參數限制并發進程的數量,默認值為CPU的核數。
直接上例子:
# -*- coding:utf-8 -*- from multiprocessing import Process,Pool import os,time def run_proc(name): ##定義一個函數用于進程調用 for i in range(5): time.sleep(0.2) #休眠0.2秒 print 'Run child process %s (%s)' % (name, os.getpid()) #執行一次該函數共需1秒的時間 if __name__ =='__main__': #執行主進程 print 'Run the main process (%s).' % (os.getpid()) mainStart = time.time() #記錄主進程開始的時間 p = Pool(8) #開辟進程池 for i in range(16): #開辟14個進程 p.apply_async(run_proc,args=('Process'+str(i),))#每個進程都調用run_proc函數, #args表示給該函數傳遞的參數。 print 'Waiting for all subprocesses done ...' p.close() #關閉進程池 p.join() #等待開辟的所有進程執行完后,主進程才繼續往下執行 print 'All subprocesses done' mainEnd = time.time() #記錄主進程結束時間 print 'All process ran %0.2f seconds.' % (mainEnd-mainStart) #主進程執行時間
執行結果:
開頭部分
Run the main process (30920).
Waiting for all subprocesses done …
Run child process Process0 (32396)
Run child process Process3 (25392)
Run child process Process1 (28732)
Run child process Process2 (32436)
末尾部分:
Run child process Process15 (25880)
All subprocesses done
All process last 2.49 seconds.
相關說明:
這里進程池對并發進程的限制數量為8個,而程序運行時會產生16個進程,進程池將自動管理系統內進程的并發數量,其余進程將會在隊列中等待。限制并發數量是因為,系統中并發的進程不是越多越好,并發進程太多,可能使CPU大部分的時間用于進程調度,而不是執行有效的計算。
采用多進程并發技術時,就單個處理機而言,其對進程的執行是串行的。但具體某個時刻哪個進程獲得CPU資源而執行是不可預知的(如執行結果的開頭部分,各進程的執行順序不定),這就體現了進程的異步性。
如果單個程序執行14次run_proc函數,那么它會需要至少16秒,通過進程的并發,這里只需要2.49秒,可見并發的優勢。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。