譯者 | 布加迪
審校 | 重樓
Python/ target=_blank class=infotextkey>Python歷來以使用方便和對程序員友好著稱,但它不是市面上速度最快的編程語言。Python的一些速度限制歸咎于它的默認實現(xiàn)CPython是單線程的。也就是說,CPython一次只使用一個硬件線程。
雖然您可以使用Python的內(nèi)置Threading(線程)模塊來加快速度,但線程只能提供并發(fā)性,而不能提供并行性。它適用于運行不依賴CPU的多個任務,但無助于為每個任務都需要一個完整CPU的多個任務提高速度。這種情況在將來可能會有所改變,而現(xiàn)在,最好假設Python中的線程不會為您提供并行性。
Python包含了一種跨多個CPU運行工作負載的原生方法。Multiprocessing(多處理)模塊啟動Python解釋器的多個副本,每個副本在一個單獨的CPU核心上,并提供用于跨核心拆分任務的原語。但有時就連多處理都不夠。
在一些情況下,作業(yè)不僅需要跨多個核心分配工作,還需要跨多個機器分配工作。這時候本文介紹的Python庫和框架就有了用武之地。您可以使用以下七個框架,將現(xiàn)有的Python應用程序及其工作負載分配到多個核心、多臺機器或兩者之間。
1.Ray
Ray由加州大學伯克利分校的一組研究人員開發(fā),它支持許多分布式機器學習庫。但Ray并不僅僅局限于機器學習任務,即使這是它最初的用例。您可以使用Ray在多個系統(tǒng)中分拆和分發(fā)任何類型的Python任務。
Ray采用極簡語法,所以您不需要對現(xiàn)有的應用程序進行大量的修改就能并行處理它們。@ray.remote裝飾器將該函數(shù)分布到Ray集群中的任何可用節(jié)點上,并可選擇指定使用多少個CPU或GPU的參數(shù)。每個分布式函數(shù)的結果都作為Python對象返回,因此它們易于管理和存儲,并且節(jié)點間或節(jié)點內(nèi)的復制量最小。比如說,在處理NumPy數(shù)組時,最后一項特性就能派得上用場。
Ray甚至包括它自己的內(nèi)置集群管理器,它可以根據(jù)需要在本地硬件或流行的云計算平臺上自動啟動節(jié)點。其他Ray庫允許您擴展常見的機器學習和數(shù)據(jù)科學工作負載,因此您不必手動構建它們。比如說,Ray Tune讓您可以為大多數(shù)常見的機器學習系統(tǒng)(其中包括PyTorch和TensorFlow)執(zhí)行大規(guī)模的超參數(shù)調(diào)優(yōu)操作。
2.Dask
從外表上看,Dask很像Ray。它也是一個用于Python分布式并行計算的庫,擁有自己的任務調(diào)度系統(tǒng),支持NumPy等Python數(shù)據(jù)框架,并且能夠從一臺機器擴展到多臺機器。
Dask與Ray的一個關鍵區(qū)別在于調(diào)度機制。Dask使用集中式調(diào)度器來處理集群的所有任務。Ray是去中心化的,這意味著每臺機器都運行自己的調(diào)度器,因此計劃任務方面的任何問題都在單個機器、而不是整個集群的層面上加以處理。Dask的任務框架與Python的原生Concurrent. Futures接口協(xié)同工作,所以對于那些使用過這個庫的人來說,關于作業(yè)如何運行的大多數(shù)隱喻應該是熟悉的。
Dask有兩種基本工作方式。第一種方式是通過并行化的數(shù)據(jù)結構——本質上是Dask自己版本的NumPy數(shù)組、列表或Pandas DataFrame。將這些結構的Dask版本換成默認值,Dask將自動在集群上分配執(zhí)行。這通常只需要更改導入的名稱,但有時可能需要重寫才能完全工作。
第二種方式是通過Dask的低級并行化機制(包括函數(shù)裝飾器),在節(jié)點之間分配作業(yè),并同步(“立即”模式下)或異步(“懶惰”模式下)返回結果。這兩種模式都可以根據(jù)需要混合使用。
Dask還提供了一個名為actor的功能。actor是指向另一個Dask節(jié)點上作業(yè)的對象。這樣一來,需要大量本地狀態(tài)的作業(yè)可以就地運行,并由其他節(jié)點遠程調(diào)用,因此不必復制作業(yè)的狀態(tài)。Ray缺乏像Dask的actor模型這樣的機制來支持更復雜的作業(yè)分配。然而,Dask的調(diào)度器并不知道actor做什么,所以如果actor失控或掛起,調(diào)度器無法進行干預。文檔是這樣描述的:“高性能但不具有彈性”,所以應該謹慎使用actor。
3.Dispy
Dispy允許您在機器集群上分配整個Python程序或僅僅單個函數(shù),以便并行執(zhí)行。它使用平臺原生機制進行網(wǎng)絡通信,以保持快速高效地運行,因此linux、macOS和windows機器都能同樣順暢地工作。這使得它成為比本文討論的其他解決方案更通用的解決方案,所以如果您需要不是專門用于加速機器學習任務的解決方案或特定的數(shù)據(jù)處理框架,那么它值得關注。
Dispy語法在某種程度上類似多處理,因為您顯式創(chuàng)建一個集群(其中多處理將讓您創(chuàng)建一個進程池),向集群提交工作,然后檢索結果。修改作業(yè)以使用Dispy可能需要做更多的工作,但是您也可以精確地控制如何分派和返回這些作業(yè)。比如說,您可以返回臨時或部分完成的結果,將文件作為作業(yè)分配過程的一部分來傳輸,并在傳輸數(shù)據(jù)時使用SSL加密。
4.Pandaral·lel
顧名思義,Pandaral·lel是一種跨多個節(jié)點并行化Pandas作業(yè)的方法。缺點是Pandaral·lel只適用于Pandas。但是如果您正在使用Pandas,并且只需要一種方法來加速單臺計算機上跨多個核心的Pandas作業(yè),Pandaral·lel將專注于處理該任務。
請注意,雖然Pandaral·lel確實在Windows上運行,但它只從在Windows Subsystem for Linux中啟動的Python會話運行。Linux和macOS用戶可以按原樣運行Pandaral·lel。
5.Ipyparallel
Ipyparallel是另一個高度專門化的多處理和任務分配系統(tǒng),專門用于跨集群并行執(zhí)行Jupyter筆記本代碼。已經(jīng)在Jupyter上工作的項目和團隊可以立即開始使用Ipyparallel。
Ipyparallel支持許多并行化代碼的方法。簡單的有map,它將任何函數(shù)應用于序列,并在可用節(jié)點上平均分配工作。針對較復雜的工作,您可以裝飾特定的函數(shù),以便始終遠程運行或并行運行。
Jupyter筆記本支持“魔法命令”,用于只能在筆記本環(huán)境中執(zhí)行的操作。Ipyparallel添加了一些自己的魔法命令。比如說,您可以在任何Python語句前加上%px前綴,以便自動并行化。
6.Joblib
Joblib有兩個主要的目標:并行運行作業(yè);如果沒有任何變化,不重新計算結果。這種效率使得Joblib非常適合科學計算,在科學計算中,可重復的結果是神圣不可侵犯的。Joblib的文檔提供了如何使用其所有特性的眾多示例。
用于并行化工作的Joblib語法非常簡單,它相當于一個裝飾器,可用于跨處理器拆分作業(yè),或緩存結果。并行作業(yè)可以使用線程或進程。
Joblib為計算作業(yè)創(chuàng)建的Python對象提供了一個透明的磁盤緩存。這個緩存不僅可以幫助Joblib避免重復工作(如上所述),還可以用于暫停和恢復長時間運行的作業(yè),或者在崩潰后恢復作業(yè)未完成的余下處理。緩存還針對NumPy數(shù)組等大型對象進行了智能優(yōu)化。通過使用numpy.memmap,可以在同一系統(tǒng)上的進程之間在內(nèi)存中共享數(shù)據(jù)區(qū)域。這一切都使得Joblib對于可能需要很長時間才能完成的工作非常有用,因為您可以避免重做現(xiàn)有工作,并根據(jù)需要暫停/恢復。
Joblib沒有提供在多臺獨立計算機上分配作業(yè)的方法。從理論上講,可以使用Joblib的管道做到這一點,但使用另一個直接支持它的框架可能來得更容易。
7.Parsl
Parsl的全稱是“并行腳本庫”,它允許您拿來計算作業(yè)后,使用與Python的現(xiàn)有Pool對象大致相同的語法將計算作業(yè)拆分到多個系統(tǒng)上。它還允許您將不同的計算任務拼接到多步驟工作流中,這些工作流可以并行運行、按順序運行,也可以通過map/reduce操作運行。
Parsl允許您執(zhí)行原生Python應用程序,但也可以通過針對shell的命令運行任何其他外部應用程序。您的Python代碼就像普通的Python代碼一樣編寫,除了一個特殊的函數(shù)裝飾器,它標記了您工作的入口點。作業(yè)提交系統(tǒng)也讓您可以精細化控制對象在目標上的運行方式,比如每個工作節(jié)點(worker)的核心數(shù)量、每個工作節(jié)點有多少內(nèi)存、CPU關聯(lián)控制以及輪詢超時的頻率等等。
Parsl提供的一項出色特性是一組預構建模板,用于將工作分派給各種高端計算資源。這不僅包括AWS或Kube.NETes集群等主要資源,還包括Blue Waters、ASPIRE 1和Frontera等超級計算資源(假設您有訪問權限)。Parsl是在許多制造此類硬件的機構的幫助下共同開發(fā)而成的。
結論
Python在線程方面的限制將繼續(xù)有所改善,主要的變化是允許線程并排運行,以完成受CPU限制的工作。但這些更新離實際可用還有數(shù)年時間。為并行性設計的庫可以在我們等待的過程中幫助填補這個空白。
原文標題:7 Python libraries for parallel processing,作者:Serdar Yegulalp