Python多進(jìn)程與多線程的使用場景詳解
前言
Python多進(jìn)程適用的場景:計算密集型(CPU密集型)任務(wù)
Python多線程適用的場景:IO密集型任務(wù)
計算密集型任務(wù)一般指需要做大量的邏輯運(yùn)算,比如上億次的加減乘除,使用多核CPU可以并發(fā)提高計算性能。
IO密集型任務(wù)一般指輸入輸出型,比如文件的讀取,或者網(wǎng)絡(luò)的請求,這類場景一般會遇到IO阻塞,使用多核CPU來執(zhí)行并不會有太高的性能提升。
下面使用一臺64核的虛擬機(jī)來執(zhí)行任務(wù),通過示例代碼來區(qū)別它們,
示例1:執(zhí)行計算密集型任務(wù),進(jìn)行1億次運(yùn)算
使用多進(jìn)程
from multiprocessing import Process
import os, time
# 計算密集型任務(wù)
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 億次運(yùn)算
res *= i
if __name__ == "__main__":
l = []
print("本機(jī)為", os.cpu_count(), "核 CPU") # 本機(jī)為64核
start = time.time()
for i in range(4):
p = Process(target=work) # 多進(jìn)程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("計算密集型任務(wù),多進(jìn)程耗時 %s" % (stop - start))
使用多線程
from threading import Thread
import os, time
# 計算密集型任務(wù)
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 億次運(yùn)算
res *= i
if __name__ == "__main__":
l = []
print("本機(jī)為", os.cpu_count(), "核 CPU") # 本機(jī)為64核
start = time.time()
for i in range(4):
p = Thread(target=work) # 多線程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("計算密集型任務(wù),多線程耗時 %s" % (stop - start))
兩段代碼輸出:
本機(jī)為 64 核 CPU
計算密集型任務(wù),多進(jìn)程耗時 6.864224672317505
本機(jī)為 64 核 CPU
計算密集型任務(wù),多線程耗時 37.91042113304138
說明:上述代碼中,分別使用4個多進(jìn)程和4個多線程去執(zhí)行億次運(yùn)算,多進(jìn)程耗時6.86s,多線程耗時37.91s,可見在計算密集型任務(wù)場景,使用多進(jìn)程能大大提高效率。
另外,當(dāng)分別使用8個多進(jìn)程和8個多線程去執(zhí)行億次運(yùn)算時,耗時差距更大,輸出如下:
本機(jī)為 64 核 CPU
計算密集型任務(wù),多進(jìn)程耗時 6.811635971069336
本機(jī)為 64 核 CPU
計算密集型任務(wù),多線程耗時 113.53767895698547
可見在64核的cpu機(jī)器下,同時使用8個多進(jìn)程和4個多進(jìn)程效率幾乎一樣。而使用多線程則就效率較慢。要最高效地利用CPU,計算密集型任務(wù)同時進(jìn)行的數(shù)量應(yīng)當(dāng)?shù)扔贑PU的核心數(shù)
示例2:400次,阻塞兩秒,讀取文件
使用多進(jìn)程(4核cpu)
from multiprocessing import Process
import os, time
# I/0密集型任務(wù)
def work():
time.sleep(5) # 阻塞兩秒
if __name__ == "__main__":
l = []
print("本機(jī)為", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Process(target=work) # 多進(jìn)程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任務(wù),多進(jìn)程耗時 %s" % (stop - start))
使用多線程(4核cpu)
from threading import Thread
import os, time
# I/0密集型任務(wù)
def work():
time.sleep(5) # 阻塞兩秒
if __name__ == "__main__":
l = []
print("本機(jī)為", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Thread(target=work) # 多線程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任務(wù),多線程耗時 %s" % (stop - start))
輸出:
本機(jī)為 64 核 CPU
I/0密集型任務(wù),多進(jìn)程耗時 12.28218412399292
本機(jī)為 64 核 CPU
I/0密集型任務(wù),多線程耗時 5.399136066436768
說明:python的多線程有于GIL鎖的存在,無論是多少核的cpu機(jī)器,也只能使用單核,從輸出結(jié)果來看,對于IO密集型任務(wù)使用多線程比較占優(yōu)。
FAQ:執(zhí)行多進(jìn)程的io密集型任務(wù)時,報了一個錯:
OSError: [Errno 24] Too many open files
原因:linux系統(tǒng)限制
ulimit -n # 輸出 1024
解決:(臨時提高系統(tǒng)限制,重啟后失效)
ulimit -n 10240
總結(jié)
到此這篇關(guān)于Python多進(jìn)程與多線程使用場景的文章就介紹到這了,更多相關(guān)Python多進(jìn)程與使用場景內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
調(diào)整Jupyter notebook的啟動目錄操作
這篇文章主要介紹了調(diào)整Jupyter notebook的啟動目錄操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
python單機(jī)五子棋的代碼實(shí)現(xiàn)示例
五子棋是經(jīng)典的棋牌類游戲,很多人都玩過,那么如何用Python實(shí)現(xiàn)五子棋呢,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10
使用pycharm運(yùn)行flask應(yīng)用程序的詳細(xì)教程
這篇文章主要介紹了使用pycharm運(yùn)行flask應(yīng)用程序,首先大家需要使用pycharm創(chuàng)建你的第一個app,接下來就開始配置pycharm,需要的朋友可以參考下2021-06-06
Python tkinter實(shí)現(xiàn)的圖片移動碰撞動畫效果【附源碼下載】
這篇文章主要介紹了Python tkinter實(shí)現(xiàn)的圖片移動碰撞動畫效果,涉及Python tkinter模塊操作圖片基于坐標(biāo)動態(tài)變換與數(shù)值判定實(shí)現(xiàn)移動、碰撞檢測等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
詳解Python手寫數(shù)字識別模型的構(gòu)建與使用
這篇文章主要為大家詳細(xì)介紹了Python中手寫數(shù)字識別模型的構(gòu)建與使用,文中的示例代碼簡潔易懂,對我們學(xué)習(xí)Python有一定的幫助,需要的可以參考一下2022-12-12

