- 1、Python 多線程效率不高嗎?
- 2、python 什麼情況下該用多線程什麼情況下不該用
- 3、python多線程能提高效率嗎
- 4、Python多線程是什麼意思?
- 5、Python高階(一) – 單線程、多線程和多進程的效率對比測試
Python效率到底高不高?到底是不是雞肋?Python由於有全鎖局的存在(同一時間只能有一個線程執行),並不能利用多核優勢。所以,如果你的多線程進程是CPU密集型的,那多線程並不能帶來效率上的提升,相反還可能會因為線程的頻繁切換,導致效率下降;如果是IO密集型,多線程進程可以利用IO阻塞等待時的空閑時間執行其他線程,提升效率。
多線程,是指從軟件或者硬件上實現多個線程並發執行的技術。想要了解不同的線程是怎樣運作的,要知道不同線程同時訪問資源時,需要使用保護機制,Python中使用GIL(解釋器全局鎖)。直觀上,這是一個加在解釋器上的全局(從解釋器的角度看)鎖。這意味着對於任何Python程序,不管有多少的處理器,任何時候都總是只有一個線程在執行。所以,如果沒有IO操作,python中的多線程比單線程效率還低。
根據我同學的說法,如果你只是想做個定時器樣的簡單東西,對穩定性要求低些,如vb,c#類似的定時器,用多線程吧,但線程的同步要注意了。python的線程更加類似定時器,python的線程不是真線程,但有的場合用這種定時器也能解決很多問題,因為開銷小,開啟也方便。但是如果你不是這種想法,你可能很難理解。
雖然CPython的線程庫直接封裝了系統的原生線程,但CPython整體作為一個進程,同一時間只會有一個獲得GIL的線程在跑,其他線程則處於等待狀態。這就造成了即使在多核CPU中,多線程也只是做着分時切換而已。
python的多線程建議在IO密集的情況下使用,反過來說如果是CPU密集的情況下就不建議使用多線程了,這個時候就需要使用多進程
如果你的代碼是CPU密集型,多個線程的代碼很有可能是線性執行的。所以這種情況下多線程是雞肋,效率可能還不如單線程因為有context switch
但是:如果你的代碼是IO密集型,多線程可以明顯提高效率。例如製作爬蟲(我就不明白為什麼Python總和爬蟲聯繫在一起…不過也只想起來這個例子…),絕大多數時間爬蟲是在等待socket返回數據。這個時候C代碼里是有release GIL的,最終結果是某個線程等待IO的時候其他線程可以繼續執行。
反過來講:你就不應該用Python寫CPU密集型的代碼…效率擺在那裡…
如果確實需要在CPU密集型的代碼里用concurrent,就去用multiprocessing庫。這個庫是基於multi process實現了類multi thread的API接口,並且用pickle部分地實現了變量共享。
再加一條,如果你不知道你的代碼到底算CPU密集型還是IO密集型,教你個方法:
multiprocessing這個module有一個dummy的sub module,它是基於multithread實現了multiprocessing的API。
假設你使用的是multiprocessing的Pool,是使用多進程實現了concurrency
from multiprocessing import Pool
如果把這個代碼改成下面這樣,就變成多線程實現concurrency
from multiprocessing.dummy import Pool
兩種方式都跑一下,哪個速度快用哪個就行了。
UPDATE:
剛剛才發現concurrent.futures這個東西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更簡單
簡單地說就是作為可能是僅有的支持多線程的解釋型語言(perl的多線程是殘疾,PHP沒有多線程),Python的多線程是有compromise的,在任意時間只有一個Python解釋器在解釋Python bytecode。
UPDATE:如評論指出,Ruby也是有thread支持的,而且至少Ruby MRI是有GIL的。
如果你的代碼是CPU密集型,多個線程的代碼很有可能是線性執行的。所以這種情況下多線程是雞肋,效率可能還不如單線程因為有context switch
但是:如果你的代碼是IO密集型,多線程可以明顯提高效率。例如製作爬蟲(我就不明白為什麼Python總和爬蟲聯繫在一起…不過也只想起來這個例子…),絕大多數時間爬蟲是在等待socket返回數據。這個時候C代碼里是有release GIL的,最終結果是某個線程等待IO的時候其他線程可以繼續執行。
反過來講:你就不應該用Python寫CPU密集型的代碼…效率擺在那裡…
如果確實需要在CPU密集型的代碼里用concurrent,就去用multiprocessing庫。這個庫是基於multi process實現了類multi thread的API接口,並且用pickle部分地實現了變量共享。
再加一條,如果你不知道你的代碼到底算CPU密集型還是IO密集型,教你個方法:
multiprocessing這個module有一個dummy的sub module,它是基於multithread實現了multiprocessing的API。
假設你使用的是multiprocessing的Pool,是使用多進程實現了concurrency
from multiprocessing import Pool
如果把這個代碼改成下面這樣,就變成多線程實現concurrency
from multiprocessing.dummy import Pool
兩種方式都跑一下,哪個速度快用哪個就行了。
UPDATE:
剛剛才發現concurrent.futures這個東西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更簡單
多線程的目的 – “最大限度地利用CPU資源”。每個程序執行時都會產生一個進程,而每一個進程至少要有一個主線程。對於單CPU來說(沒有開啟超線程),在同一時間只能執行一個線程,所以如果想實現多任務,那麼就只能每個進程或線程獲得一個時間片,在某個時間片內,只能一個線程執行,然後按照某種策略換其他線程執行。由於時間片很短,這樣給用戶的感覺是同時有好多線程在執行。
Python是運行在解釋器中的語言,查找資料知道,python中有一個全局鎖(GIL),在使用多線程(Thread)的情況下,不能發揮多核的優勢。而使用多進程(Multiprocess),則可以發揮多核的優勢真正地提高效率。
單線程、多線程和多進程的效率對比測試: github地址
資料顯示,如果多線程的進程是CPU密集型的,那多線程並不能有多少效率上的提升,相反還可能會因為線程的頻繁切換,導致效率下降,推薦使用多進程;如果是IO密集型,多線程進程可以利用IO阻塞等待時的空閑時間執行其他線程,提升效率。所以我們根據實驗對比不同場景的效率
| CPU密集型操作| IO密集型操作| 網絡請求密集型操作
— | — | –| —
線性操作| 69.73533328374 |17.76633326213 | 6.78833333651
多線程操作| 75.40299995740 |145.68366670609 | 1.93999997775
多進程操作| 13.97433336576 | 4.67833328247| 2.38333328565
僅個人觀點,,歡迎留言~~~
原創文章,作者:簡單一點,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/126883.html