這篇文章主要講解了“Python多進程怎么應(yīng)用”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Python多進程怎么應(yīng)用”吧!
創(chuàng)新互聯(lián)2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元博興做網(wǎng)站,已為上家服務(wù),為博興各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792
想象一下,你有一個巨大的問題要解決,而你獨自一人。你需要計算八個不同數(shù)字的平方根。你是做什么的?你沒有太多選擇。從第一個數(shù)字開始,然后計算結(jié)果。然后,你繼續(xù)和其他人。
如果你有三個擅長數(shù)學的朋友愿意幫助你呢?他們每個人都會計算兩個數(shù)字的平方根,你的工作會更容易,因為工作量在你的朋友之間平均分配。這意味著你的問題將更快地得到解決。
好了,一切都清楚了嗎?在這些示例中,每個朋友代表CPU的核心。在第一個示例中,整個任務(wù)由你依次解決。這稱為串行計算。在第二個示例中,由于你總共使用了四個內(nèi)核,因此你使用的是并行計算。并行計算涉及使用并行進程或在處理器的多個核之間劃分的進程。
我們已經(jīng)確定了什么是并行編程,但我們?nèi)绾问褂盟??我們之前說過,并行計算涉及在處理器的多個核心之間執(zhí)行多個任務(wù),這意味著這些任務(wù)是同時執(zhí)行的。在進行并行化之前,你應(yīng)該考慮幾個問題。例如,是否有其他優(yōu)化可以加快我們的計算速度?
現(xiàn)在,讓我們理所當然地認為并行化是最適合的解決方案。并行計算主要有三種模式:
完全平行。任務(wù)可以獨立運行,不需要相互通信。
共享內(nèi)存并行。進程(或線程)需要通信,因此它們共享一個全局地址空間。
消息傳遞。進程需要在需要時共享消息。
在本文中,我們將說明第一個模型,它也是最簡單的。
在 Python 中實現(xiàn)并行性的一種方法是使用multiprocessing模塊。multiprocessing
模塊允許你創(chuàng)建多個進程,每個進程都有自己的 Python 解釋器。因此,Python 多進程實現(xiàn)了基于進程的并行。
你可能聽說過其他庫,比如threading
,它也是Python內(nèi)置的,但它們之間有著重要的區(qū)別。multiprocessing
模塊創(chuàng)建新進程,而threading
創(chuàng)建新線程。
你可能會問,“為什么選擇多進程?” 多進程可以通過并行而不是按順序運行多個任務(wù)來顯著提高程序的效率。一個類似的術(shù)語是多線程,但它們是不同的。
進程是加載到內(nèi)存中運行的程序,不與其他進程共享其內(nèi)存。線程是進程中的一個執(zhí)行單元。多個線程在一個進程中運行,并相互共享進程的內(nèi)存空間。
Python的全局解釋器鎖(GIL)只允許在解釋器下一次運行一個線程,這意味著如果需要Python解釋器,你將無法享受多線程的性能優(yōu)勢。這就是在Python中多進程比線程更占優(yōu)勢的原因。多個進程可以并行運行,因為每個進程都有自己的解釋器,執(zhí)行分配給它的指令。此外,操作系統(tǒng)將在多個進程中查看你的程序,并分別對它們進行調(diào)度,即,你的程序在總的計算機資源中占有更大的份額。因此,當程序受到CPU限制時,多進程速度更快。在程序中有大量I/O的情況下,線程可能更高效,因為大多數(shù)時候,程序都在等待I/O完成。然而,多進程通常效率更高,因為它同時運行。
以下是多進程的一些好處:
在處理高CPU密集型任務(wù)時更好地使用CPU
與線程相比,對子線程的控制更多
易于編碼
第一個優(yōu)點與性能有關(guān)。由于多進程創(chuàng)建了新的進程,你可以通過在其他內(nèi)核之間劃分任務(wù)來更好地利用CPU的計算能力。現(xiàn)在大多數(shù)處理器都是多核處理器,如果你優(yōu)化代碼,可以通過并行計算節(jié)省時間。
第二個優(yōu)點是多線程處理的替代方案。線程不是進程,這有其后果。如果你創(chuàng)建了一個線程,那么像處理正常進程一樣終止它甚至中斷它是很危險的。由于多進程和多線程之間的比較不在本文的范圍內(nèi),后續(xù)我會單獨寫一篇來講講多進程和多線程的區(qū)別。
多進程的第三個優(yōu)點是它很容易實現(xiàn),因為你嘗試處理的任務(wù)適合并行編程。
我們終于準備好編寫一些 Python 代碼了!
我們將從一個非?;镜氖纠_始,我們將使用它來說明 Python 多進程的核心方面。在此示例中,我們將有兩個進程:
parent
經(jīng)常。只有一個父進程,它可以有多個子進程。
child
進程。這是由父進程產(chǎn)生的。每個子進程也可以有新的子進程。
我們將使用該child
過程來執(zhí)行某個函數(shù)。這樣,parent
可以繼續(xù)執(zhí)行。
這是我們將用于此示例的代碼:
from multiprocessing import Process def bubble_sort(array): check = True while check == True: check = False for i in range(0, len(array)-1): if array[i] > array[i+1]: check = True temp = array[i] array[i] = array[i+1] array[i+1] = temp print("Array sorted: ", array) if __name__ == '__main__': p = Process(target=bubble_sort, args=([1,9,4,5,2,6,8,4],)) p.start() p.join()
在這個片段中,我們定義了一個名為bubble_sort(array)
。這個函數(shù)是冒泡排序算法的一個非常簡單的實現(xiàn)。如果你不知道它是什么,請不要擔心,因為它并不重要。要知道的關(guān)鍵是它是一個可以實現(xiàn)某個功能的函數(shù)。
從multiprocessing
,我們導入類Process
。此類表示將在單獨進程中運行的活動。事實上,你可以看到我們已經(jīng)傳遞了一些參數(shù):
target=bubble_sort
,意味著我們的新進程將運行該bubble_sort
函數(shù)
args=([1,9,4,52,6,8,4],)
,這是作為參數(shù)傳遞給目標函數(shù)的數(shù)組
一旦我們創(chuàng)建了 Process 類的實例,我們只需要啟動該進程。這是通過編寫p.start()
完成的。此時,該進程開始。
在我們退出之前,我們需要等待子進程完成它的計算。該join()
方法等待進程終止。
在這個例子中,我們只創(chuàng)建了一個子進程。正如你可能猜到的,我們可以通過在Process
類中創(chuàng)建更多實例來創(chuàng)建更多子進程。
如果我們需要創(chuàng)建多個進程來處理更多 CPU 密集型任務(wù)怎么辦?我們是否總是需要明確地開始并等待終止?這里的解決方案是使用Pool
類。
Pool
類允許你創(chuàng)建一個工作進程池,在下面的示例中,我們將研究如何使用它。這是我們的新示例:
from multiprocessing import Pool import time import math N = 5000000 def cube(x): return math.sqrt(x) if __name__ == "__main__": with Pool() as pool: result = pool.map(cube, range(10,N)) print("Program finished!")
在這個代碼片段中,我們有一個cube(x)
函數(shù),它只接受一個整數(shù)并返回它的平方根。很簡單,對吧?
然后,我們創(chuàng)建一個Pool
類的實例,而不指定任何屬性。默認情況下,Pool
類為每個 CPU 核心創(chuàng)建一個進程。接下來,我們使用幾個參數(shù)運行map
方法。
map
方法將cube
函數(shù)應(yīng)用于我們提供的可迭代對象的每個元素——在本例中,它是從10
到N
的每個數(shù)字的列表。
這樣做的最大優(yōu)點是列表上的計算是并行進行的!
包joblib
是一組使并行計算更容易的工具。它是一個用于多進程的通用第三方庫。它還提供緩存和序列化功能。要安裝joblib
包,請在終端中使用以下命令:
pip install joblib
我們可以將之前的示例轉(zhuǎn)換為以下示例以供使用joblib
:
from joblib import Parallel, delayed def cube(x): return x**3 start_time = time.perf_counter() result = Parallel(n_jobs=3)(delayed(cube)(i) for i in range(1,1000)) finish_time = time.perf_counter() print(f"Program finished in {finish_time-start_time} seconds") print(result)
事實上,直觀地看到它的作用。delayed()
函數(shù)是另一個函數(shù)的包裝器,用于生成函數(shù)調(diào)用的“延遲”版本。這意味著它在被調(diào)用時不會立即執(zhí)行函數(shù)。
然后,我們多次調(diào)用delayed
函數(shù),并傳遞不同的參數(shù)集。例如,當我們將整數(shù)1
賦予cube
函數(shù)的延遲版本時,我們不計算結(jié)果,而是分別為函數(shù)對象、位置參數(shù)和關(guān)鍵字參數(shù)生成元組(cube, (1,), {})
。
我們使用Parallel()
創(chuàng)建了引擎實例。當它像一個以元組列表作為參數(shù)的函數(shù)一樣被調(diào)用時,它將實際并行執(zhí)行每個元組指定的作業(yè),并在所有作業(yè)完成后收集結(jié)果作為列表。在這里,我們創(chuàng)建了n_jobs=3
的Parallel()
實例,因此將有三個進程并行運行。
我們也可以直接編寫元組。因此,上面的代碼可以重寫為:
result = Parallel(n_jobs=3)((cube, (i,), {}) for i in range(1,1000))
使用joblib
的好處是,我們可以通過簡單地添加一個附加參數(shù)在多線程中運行代碼:
result = Parallel(n_jobs=3, prefer="threads")(delayed(cube)(i) for i in range(1,1000))
這隱藏了并行運行函數(shù)的所有細節(jié)。我們只是使用與普通列表理解沒有太大區(qū)別的語法。
創(chuàng)建多個進程并進行并行計算不一定比串行計算更有效。對于 CPU 密集度較低的任務(wù),串行計算比并行計算快。因此,了解何時應(yīng)該使用多進程非常重要——這取決于你正在執(zhí)行的任務(wù)。
為了讓你相信這一點,讓我們看一個簡單的例子:
from multiprocessing import Pool import time import math N = 5000000 def cube(x): return math.sqrt(x) if __name__ == "__main__": # first way, using multiprocessing start_time = time.perf_counter() with Pool() as pool: result = pool.map(cube, range(10,N)) finish_time = time.perf_counter() print("Program finished in {} seconds - using multiprocessing".format(finish_time-start_time)) print("---") # second way, serial computation start_time = time.perf_counter() result = [] for x in range(10,N): result.append(cube(x)) finish_time = time.perf_counter() print("Program finished in {} seconds".format(finish_time-start_time))
此代碼段基于前面的示例。我們正在解決同樣的問題,即計算N
個數(shù)的平方根,但有兩種方法。第一個涉及 Python 進程的使用,而第二個不涉及。我們使用time
庫中的perf_counter()
方法來測量時間性能。
在我的電腦上,我得到了這個結(jié)果:
> python code.py Program finished in 1.6385094 seconds - using multiprocessing --- Program finished in 2.7373942999999996 seconds
如你所見,相差不止一秒。所以在這種情況下,多進程更好。
讓我們更改代碼中的某些內(nèi)容,例如N
的值。 讓我們把它降低到N=10000
,看看會發(fā)生什么。
這就是我現(xiàn)在得到的:
> python code.py Program finished in 0.3756742 seconds - using multiprocessing --- Program finished in 0.005098400000000003 seconds
發(fā)生了什么?現(xiàn)在看來,多進程是一個糟糕的選擇。為什么?
與解決的任務(wù)相比,在進程之間拆分計算所帶來的開銷太大了。你可以看到在時間性能方面有多大差異。
感謝各位的閱讀,以上就是“Python多進程怎么應(yīng)用”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Python多進程怎么應(yīng)用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
當前題目:Python多進程怎么應(yīng)用
網(wǎng)站地址:http://www.rwnh.cn/article14/jgpgde.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計公司、服務(wù)器托管、動態(tài)網(wǎng)站、靜態(tài)網(wǎng)站、網(wǎng)站改版、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)