python多線程對(duì)多核cpu的利用解析
引言
我們經(jīng)常聽(tīng)到"因?yàn)镚IL的存在,python的多線程不能利用多核CPU",現(xiàn)在我們暫且不提GIL,python能不能利用多核cpu,今天我做了一個(gè)實(shí)驗(yàn),代碼很簡(jiǎn)單如下所示
while 1: pass
沒(méi)有運(yùn)行這段代碼前cpu狀態(tài)
運(yùn)行之后的狀態(tài)
下面兩張圖是運(yùn)行之后的狀態(tài),當(dāng)然這只是兩張比較有代表性的圖,截圖間隔有十幾秒的樣子
根據(jù)第一張圖我們發(fā)現(xiàn)cpu1、cpu3的負(fù)載有明顯增長(zhǎng),我們可以得出python線程是可以利用多核cpu的結(jié)論,之前一直以為python運(yùn)行后會(huì)綁定cpu其中的一個(gè)核心現(xiàn)在看來(lái)并不是這個(gè)樣子。第二張圖就比較有意思了cpu2滿載了,這又是為什么呢?
想來(lái)想去應(yīng)該是linux中cpu對(duì)進(jìn)程的親和性導(dǎo)致的,這種親和性是軟性的并不是強(qiáng)制的,這也就解釋了為什么第一張圖中是多cpu在負(fù)載。
ok為了更直觀的看出python線程能夠利用多核cpu,我們改下代碼,換一種方式再來(lái)看下
import os while 1: print os.getpid() # 輸出進(jìn)程號(hào)
運(yùn)行代碼結(jié)果
一目了然,線程的確在不同的核心上切換。
現(xiàn)在我們回過(guò)頭看下那句經(jīng)典的話"因?yàn)镚IL的存在,python的多線程不能利用多核CPU",這句話很容易讓人理解成GIL會(huì)讓python在一個(gè)核心上運(yùn)行,有了今天的例子我們?cè)賮?lái)重新理解這句話,GIL的存在讓python在同一時(shí)刻只能有一個(gè)線程在運(yùn)行,這毋庸置疑,但是它并沒(méi)有給線程鎖死或者說(shuō)指定只能在某個(gè)cpu上運(yùn)行,另外我需要說(shuō)明一點(diǎn)的是GIL是與進(jìn)程對(duì)應(yīng)的,每個(gè)進(jìn)程都有一個(gè)GIL。
python線程的執(zhí)行流程理解
線程 ——>搶GIL——>CPU
這種執(zhí)行流程導(dǎo)致了CPU密集型的多線程程序雖然能夠利用多核cpu時(shí)跟單核cpu是差不多的,并且由于多個(gè)線程搶GIL這個(gè)環(huán)節(jié)導(dǎo)致運(yùn)行效率<=單線程。
看到這可能會(huì)讓人產(chǎn)生一種錯(cuò)覺(jué),有了GIL后python是線程安全的,好像根本不需要線程鎖,而實(shí)際情況是線程拿到CPU資源后并不是一直執(zhí)行的,python解釋器在執(zhí)行了該線程100條字節(jié)碼(注意是字節(jié)碼不是代碼)時(shí)會(huì)釋放掉該線程的GIL,如果這時(shí)候沒(méi)有加鎖那么其他線程就可能修改該線程用到的資源;
遇到IO也會(huì)釋放GIL
另外一個(gè)問(wèn)題是遇到IO也會(huì)釋放GIL,下面是這兩種情況的例子
import threading a = [] def m1(): for _ in range(100000): a.append(1) def m2(): for _ in range(100000): a.append(2) def check(): """ 檢查a是否有序 """ for i in range(len(a)): if i != 0: if a[i] < a[i-1]: print a[i-1], a[i] return False return True t1 = threading.Thread(target=m1) t2 = threading.Thread(target=m2) t1.start() t2.start() t1.join() t2.join() print check()
預(yù)期1111...22222...,截圖顯示跟預(yù)期的不同
import threading text1 = '1' * 10000 text2 = '2' * 10000 def write(text): with open('test.txt', 'a') as f: f.write(text) def m1(): write(text1) def m2(): write(text2) t1 = threading.Thread(target=m1) t2 = threading.Thread(target=m2) t1.start() t2.start() t1.join() t2.join()
test.txt截圖
最后結(jié)論是,因?yàn)镚IL的存在,python的多線程雖然可以利用多核CPU,但并不能讓多個(gè)核同時(shí)工作。
以上就是python多線程對(duì)多核cpu的利用解析的詳細(xì)內(nèi)容,更多關(guān)于python多線程利用多核cpu的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python獲取當(dāng)前路徑實(shí)現(xiàn)代碼
這篇文章主要介紹了 Python獲取當(dāng)前路徑實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05使用python加密主機(jī)文件幾種方法實(shí)現(xiàn)
本文主要介紹了使用python加密主機(jī)文件幾種方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02python把數(shù)組中的數(shù)字每行打印3個(gè)并保存在文檔中的方法
今天小編就為大家分享一篇python把數(shù)組中的數(shù)字每行打印3個(gè)并保存在文檔中的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07python爬蟲(chóng)通過(guò)增加多線程獲取數(shù)據(jù)
這篇文章主要為大家介紹了python爬蟲(chóng)通過(guò)增加多線程獲取數(shù)據(jù)實(shí)現(xiàn)過(guò)程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06關(guān)于使用python反編譯apk簽名出包的問(wèn)題
這篇文章主要介紹了使用python反編譯apk簽名出包,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03