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