Uber正式开源分布式机器学习平台Fiber
Uber 開發了 POET、Go-Explore 和 GTN 等算法,這些算法利用大量的計算來訓練神經網絡模型。為了使未來幾代類似算法的大規模計算成為可能,Uber 進而開發了一種新的分布式計算庫 Fiber,它可以幫助用戶輕松地將本地計算方法擴展到成百上千臺機器上。Fiber 可以使使用 Python 的大規模計算項目變得快速、簡單和資源高效,從而簡化 ML 模型訓練過程,并獲得更優的結果。
本文最初發布于 Uber 工程博客,由 InfoQ 中文站翻譯并分享。
項目地址:https://github.com/uber/fiber
在過去的幾年中,計算機不斷增強的處理能力推動了機器學習的進步。算法越來越多地利用并行性,并依賴分布式訓練來處理大量數據。然而,隨之而來的是增加數據和訓練的需求,這對管理和利用大規模計算資源的軟件提出了巨大的挑戰。
在 Uber,我們開發了POET、Go-Explore和GTN等算法,這些算法利用大量的計算來訓練神經網絡模型。為了使未來幾代類似算法的大規模計算成為可能,我們開發了一種新的分布式計算庫Fiber,它可以幫助用戶輕松地將本地計算方法擴展到成百上千臺機器上。Fiber 可以使使用 Python 的大規模計算項目變得快速、簡單和資源高效,從而簡化 ML 模型訓練過程,并獲得更優的結果。
大規模分布式計算的挑戰
在理想情況下,將運行在一臺機器上的應用程序擴展為運行在一批機器上的應用程序應該很容易,只需更改命令行參數即可。然而,在現實世界中,這并不容易。
我們每天都與許多運行大規模分布式計算任務的人一起工作,我們發現,現在很難利用分布式計算的原因有以下幾個:
-
在筆記本或臺式機本地運行代碼與在生產集群上運行代碼之間存在著巨大的差距。你可以讓MPI在本地運行,但在計算機集群上運行它是完全不同的過程。
-
不能動態擴展。如果你啟動了一個需要大量資源的作業,那么你很可能需要等待,直到所有資源都分配好了才可以運行該作業。這個等待降低了擴展的效率。
-
錯誤處理缺失。在運行時,有些作業可能會失敗。你可能不得不還原部分結果或整個地放棄本次運行。
-
學習成本很高。每個系統都有不同的 API 和編程約定。要使用新系統啟動作業,用戶必須學習一套全新的約定。
新的 Fiber 平臺專門解決了這些問題。它為更廣泛的用戶群體提供了無縫使用大規模分布式計算的可能。
Fiber 簡介
Fiber 是一個用于現代計算機集群的基于 Python 的分布式計算庫。用戶可以利用這個系統針對整個計算機集群進行編程,而不是只針對單個臺式機或筆記本電腦。它最初是為了支持像POET這樣的大規模并行科學計算項目而開發的,Uber 也已經用它來支持類似的項目。Fiber 的功能非常強大,這樣主要是因為:
-
易于使用。Fiber 允許用戶編寫在計算機集群上運行的程序,而不需要深入研究計算機集群的細節。
-
易于學習。Fiber 提供了與 Python 標準多處理庫相同的 API。知道如何使用多處理庫的工程師可以很容易地用 Fiber 編寫計算機集群程序。
-
快速可靠。Fiber 的通信中樞基于Nanomsg構建,這是一個高性能異步消息傳遞庫,可以提供快速、可靠的通信。
-
不需要部署。Fiber 在計算機集群上的運行方式與普通應用程序相同。它會自動為用戶處理資源分配和通信。
-
提供了可靠的計算。Fiber 內置的錯誤處理功能讓用戶可以專注于編寫實際的應用程序代碼,而不是處理崩潰問題。當運行一個工作進程池時,這尤其有價值。
除了這些好處之外,Fiber 還可以在特別關注性能的領域與其他專用框架搭配使用。例如,對于隨機梯度下降(SGD),Fiber 的Ring 特性可以幫助我們在計算機集群上建立分布式訓練作業,并允許它與Horovod或torch.distributed協同。
圖 1:Fiber 啟動許多不同的作業支持(job-backed)進程,然后在其中運行不同的 Fiber 組件和用戶進程。Fiber Master 是管理所有其他進程的主進程。有些進程(如 Ring Node)保持成員之間的通信。
Fiber 可以幫助從事大規模分布式計算的用戶減少從產生想法到在計算集群上實際運行分布式作業的時間。它還可以幫助用戶屏蔽配置和資源分配任務的繁瑣細節,并且可以縮短調試周期,簡化從本地開發到集群開發的轉換。
架構
Fiber 讓我們可以靈活地為經典的多處理 API 選擇可以在不同集群管理系統上運行的后端。為了實現這種集成,Fiber 被分為三個不同的層:API 層、后端層和集群層。API 層為 Fiber 提供了進程、隊列、池和管理器等基本構建塊。它們具有與多處理相同的語義,但是我們對它們進行擴展了,使它們可以在分布式環境中工作。后端層處理在不同集群管理器上創建或終止作業的任務。當用戶新增一個后端時,所有其他 Fiber 組件(隊列、池等)都不需要更改。最后,集群層由不同的集群管理器組成。盡管它們不是 Fiber 本身的一部分,但是它們幫助 Fiber 管理資源并跟蹤不同的作業,減少了 Fiber 所需要跟蹤的項的數量。圖 2 是總體架構圖:
圖 2:Fiber 的架構包括 API 層、后端層和集群層,這讓它可以在不同的集群管理系統上運行。
作業支持進程
Fiber 引入了一個新的概念,稱為作業支持過程(也稱為 Fiber 進程)。這些進程與 Python 多處理庫中的進程類似,但是更靈活:多處理庫中的進程只在本地機器上運行,但 Fiber 進程可以在不同的機器上遠程運行,也可以在同一機器上本地運行。當新的 Fiber 進程啟動時,Fiber 會在當前計算機集群上創建一個具有適當 Fiber 后端的新作業。
圖 3:Fiber 中的每個作業支持進程都是在計算機集群上運行的一個容器化作業。每個作業支持進程也有自己的 CPU、GPU 和其他計算資源。在容器內運行的代碼是自包含的。
Fiber 使用容器來封裝當前進程的運行環境(如上圖 3 所示),其中包括所有必需的文件、輸入數據和其他依賴的程序包,而且要保證每個元素都是自包含的。所有子進程都以與父進程相同的容器鏡像啟動,以確保運行環境的一致性。因為每個進程都是一個集群作業,所以它的生命周期與集群上的任何作業相同。為了方便用戶,Fiber 被設計成直接與計算機集群管理器交互。因此,不像Apache Spark或ipyparallel,Fiber 不需要在多臺機器上設置,也不需要通過任何其他機制引導。它只需要作為一個普通的 Python pip 包安裝在一臺機器上。
組件
Fiber 基于 Fiber 進程實現了大多數多處理 API,包括管道、隊列、池和管理器。
Fiber 中隊列和管道的行為方式與多處理相同。不同之處在于,Fiber 中的隊列和管道由運行在不同機器上的多個進程共享。兩個進程可以從同一個管道讀取和寫入數據。此外,隊列可以在不同機器上的多個進程之間共享,每個進程可以同時向同一隊列發送或從同一隊列接收信息。Fiber 隊列是用高性能異步消息隊列系統 Nanomsg 實現的。
圖 4:Fiber 可以在不同的 Fiber 進程之間共享隊列。在本例中,一個 Fiber 進程與隊列位于同一臺機器上,另外兩個進程位于另一臺機器上。一個進程寫入隊列,另外兩個進程讀取隊列。
Fiber 也支持池,如下圖 5 所示。它們讓用戶可以管理工作進程池。Fiber 使用作業支持進程擴展池,以便每個池可以管理數千個(遠程)工作進程。用戶還可以同時創建多個池。
圖 5:在具有三個工作進程的池中,如本例所示,兩個工作進程位于一臺機器上,另一個位于另一臺機器上。它們共同處理提交到主進程中任務隊列的任務,并將結果發送到結果隊列。
管理器和代理對象使 Fiber 能夠支持共享存儲,這在分布式系統中至關重要。通常,這個功能由計算機集群外部存儲系統如 Cassandra 和 Redis 提供。相反,Fiber 為應用程序提供了內置的內存存儲。該接口與多處理系統中的管理器類型接口相同。
Ring 是對多處理 API 的擴展,可以用于分布式計算設置。在 Fiber 中,Ring 指的是一組共同工作的、相對平等的進程。與池不同,Ring 沒有主進程和輔助進程的概念。Ring 內的所有成員承擔大致相同的責任。Fiber 的 Ring 模型拓撲(如下圖 6 所示)在機器學習分布式 SGD 中非常常見,torch.distributed和Horovod就是例子。一般來說,在一個計算機集群上啟動這種工作負載是非常具有挑戰性的;Fiber 提供 Ring 特性就是為了幫助建立這樣的拓撲。
圖 6:在一個有四個節點的 Fiber Ring 中,Ring 節點 0 和 Ring 節點 3 運行在同一臺機器上,但在兩個不同的容器中。Ring 節點 1 和節點 2 都在單獨的機器上運行。所有這些進程共同運行同一函數的副本,并在運行期間相互通信。
應用程序
借助上述靈活的組件,我們現在可以使用 Fiber 構建應用程序了。在這一節中,我們將展示兩種使用 Fiber 幫助用戶構建分布式應用程序的方式。
賦能新應用程序
在下面的例子中,我們將展示工程師如何運用 Fiber 來實現大規模分布式計算。這個例子演示的是一個強化學習(RL)算法。通常,分布式 RL 的通信模式涉及在機器之間發送不同類型的數據,包括動作、神經網絡參數、梯度、per-step/episode 觀察及獎勵。
Fiber 實現了管道和池來傳輸這些數據。在底層,池是普通的 Unix 套接字,為使用 Fiber 的應用程序提供接近線路速度的通信。現代計算機網絡的帶寬通常高達每秒幾百千兆。通過網絡傳輸少量數據通常速度很快。
此外,如果有許多不同的進程向一個進程發送數據,進程間通信延遲也不會增加太多,因為數據傳輸可以并行進行。事實證明,Fiber 池可以作為許多 RL 算法的基礎,因為模擬器可以在各個池工作進程中運行,并且結果可以并行回傳。
下面的示例顯示了使用 Fiber 實現的簡化 RL 代碼:
# fiber.BaseManager is a manager that runs remotely class RemoteEnvManager (fiber.managers.AsyncManager): pass class Env (gym.env): # gym env pass RemoteEnvManager.register (‘Env’, Env) def build_model (): # create a new policy model return model def update_model (model, observations): # update model with observed data return new_model def train (): model = build_model () manager = RemoteEnvManager () num_envs = 10 envs = [manager.Env () for i in range (num_envs)] handles = [envs[i].reset () for i in num_envs] obs = [handle.get () for handle in handles] for i in range (1000): actions = model (obs) handles = [env.step () for action in actions] obs = [handle.get () for handle in handles] model = update_model (model, obs)
賦能現有的多處理應用程序
許多 Python 用戶利用了多處理。Fiber 為此類應用程序提供了更多的機會,通過這種系統,只需更改幾行代碼,就可以在類似于 Kubernetes 的計算機集群上的分布式設置中運行。
例如,OpenAI Baselines是一個非常流行的 RL 庫,它有許多參考算法,比如DQN和PPO。它的缺點是只能在一臺機器上工作。如果希望大規模地訓練 PPO,就必須創建自己的基于 MPI 的系統并手動設置集群。
相比之下,有了 Fiber,事情就簡單多了。它可以無縫地擴展像 PPO 這樣的 RL 算法,從而利用分布式環境的數百個工作進程。Fiber 提供了與多處理相同的 API,OpenAI Baselines 就是使用這些 API 在本地獲取多核 CPU 的處理能力。要讓 OpenAI Baselines 使用 Fiber,只需要修改一行代碼:
修改完這行代碼,OpenAI Baselines 就可以在 Kubernetes 上運行了。我們在這里提供了在 Kubernetes 上運行 OpenAI Baselines 的完整指南。
錯誤處理
Fiber 實現了基于池的錯誤處理。在創建新池時,還將創建關聯的任務隊列、結果隊列和掛起表。然后,用戶可以將新創建的任務添加到任務隊列中。該任務隊列由主進程和工作進程共享。每個工作進程從任務隊列中獲取一個任務,然后在該任務中運行任務函數。每當用戶從任務隊列中刪除一個任務時,Fiber 就會在掛起表中添加一個條目。工作進程完成該任務后會將結果放入結果隊列中。然后,Fiber 從掛起表中刪除與該任務相關的條目。
圖 7:上圖是一個包含四個工作進程的普通 Fiber 池。在下圖,Worker 3 出現故障,因此 Fiber 啟動一個新的工作進程(Worker 5),然后準備將其添加到池中。
如果池里有一個工作進程在處理過程中失敗,如上圖 7 所示,父池作為所有工作進程的進程管理器將會檢測到該失敗。然后,如果這個失敗的進程有掛起任務,則父池會將掛起表中的掛起任務放回到任務隊列中。接下來,它啟動一個新的工作進程來替換之前失敗的進程,并將新創建的工作進程綁定到任務隊列和結果隊列。
性能
Fiber 最重要的應用之一是擴展計算算法(如 RL) 和基于群體的方法(如 ES)。在這些應用程序中,延遲非常關鍵。RL 和基于群體的方法經常應用于需要與模擬器(如ALE、Gym和Mujoco)頻繁交互以評估策略和收集經驗的設置中。等待模擬器結果所帶來的延遲嚴重影響了整體的訓練性能。
為了測試 Fiber,我們將其性能與其他框架進行了比較。我們還在框架開銷測試中增加了Ray,以提供一些初步結果,并希望在將來添加更詳細的結果。
通常有兩種方法可以減少 RL 算法和基于群體的方法的延遲。要么我們可以減少需要傳輸的數據量,要么我們可以提升不同進程之間通信通道的速度。為了加快通信處理,Fiber 使用 Nanomsg 實現了管道和池。此外,用戶還可以使用speedus這樣的庫進一步提高性能。
框架開銷
通常,框架中的組件會影響計算資源,因此,我們測試了 Fiber 的開銷。我們比較了 Fiber、Python 多處理庫、Apache Spark、Ray 和 ipyparallel。在測試過程中,我們創建了一批工作負載,完成這些任務所需的總時間是固定的。每個任務的持續時間從 1 秒到 1 毫秒不等。
對于每個框架,我們在本地運行了 5 個工作進程,并通過調整批次的大小來確保每個框架的總耗時大約為 1 秒(即 1 毫秒的任務,我們運行了 5000 個)。我們假設,Fiber 的性能應該和多處理差不多,因為 Fiber 和多處理都不依賴于復雜的調度機制。相反,我們認為 Apache Spark、Ray 和 ipyparallel 會比 Fiber 慢,因為它們中間依賴于調度器。
圖 8:在測試 Fiber、Python 多處理庫、Apache Spark 和 ipyprallel 的框架開銷時,我們在本地運行了 5 個工作進程,并調整批次大小,使每個框架在大約 1 秒鐘內完成任務。
當任務持續時間為 100 毫秒或更多時,Fiber 幾乎沒有表現出任何差異,當任務持續時間降至 10 毫秒或 1 毫秒時,它比其他框架更接近多處理庫。
我們以多處理作為參考,因為它非常輕量級,除了創建新進程和并行運行任務外沒有實現任何其他特性。此外,它還利用了僅在本地可用的通信機制(例如共享內存、Unix 域套接字等)。這使得支持分布式資源管理系統的其他框架難以超越多處理,因為這些系統無法利用類似的機制。
圖 9:我們的開銷測試顯示,Fiber 的執行情況與 Python 多處理庫類似,在 1 毫秒處,ipyparallel 和 Apache Spark 處理任務的耗時更長。最佳完成時間為 1 秒。
與 Fiber 相比,ipyparallel 和 Apache Spark 在每個任務持續時間上都落后很多。當任務持續時間為 1 毫秒時,ipyparallel 花費的時間幾乎是 Fiber 的 24 倍,Apache Spark 花費的時間是后者的 38 倍。顯然,當任務持續時間較短時,ipyparallel 和 Apache Spark 都引入了相當大的開銷,而且,對于 RL 和基于群體的方法,它們不如 Fiber 合適,后者使用了模擬器,響應時間只有幾毫秒。我們還可以看到,在運行 1 毫秒的任務時,Ray 花費的時間大約是 Fiber 的 2.5 倍。
分布式任務測試
為了探究 Fiber 的可伸縮性和效率,我們將其與 ipyparallel 進行了比較,由于之前的性能測試結果,我們沒有考慮 Apache Spark。我們也排除了 Python 多處理庫,因為它不能擴展到一臺機器之外。我們運行了 50 次進化策略迭代(ES),根據它們的耗時對比了 Fiber 和 ipyparallel 的可伸縮性和效率。
在工作負載相同的情況下,我們預計 Fiber 可以完成得更快,因為前面已測試過,它的開銷比 ipyparallel 小得多。對于 Fiber 和 ipyparallel,我們使用的群體大小為 2048,因此,無論工作進程的數量多少,總計算量都是固定的。我們還在兩者中實現了相同的共享噪音表,每八個工作進程共享一個噪音表。這項工作的實驗域是OpenAI GymBipedal Walker Hardcore 環境的一個修改版本,這里對修改進行了描述。
圖 10:當 ES 迭代 50 次以上時,使用不同數量的工作進程運行 ES,Fiber 的擴展性均優于 ipyparallel。每個工作進程在單個 CPU 上運行。
主要結果是,Fiber 的擴展性比 ipyparallel 更好,并且完成每次測試的速度明顯更快。隨著工作進程數從 32 增加到 1024,Fiber 的運行時間逐漸縮短。相比之下,當工作進程數從從 256 增加到 512 時,ipyparallel 的運行時間逐漸變長。在使用 1024 個工作進程時,由于進程之間的通信錯誤,ipyparallel 未能完成運行。這個失敗削弱了 ipyparallel 運行大規模并行計算的能力。根據Amdahl 定律,我們看到,當工作進程數增加到 512 以上時,Fiber 的收益會減少。在這種情況下,主進程處理數據的速度就會成為瓶頸。
總的來說,在所有工作進程數的測試中,Fiber 的性能都超過了 ipyparallel。此外,與 ipyparallel 不同的是,Fiber 在運行 1024 個工作進程時也完成了這項工作。這個結果更能顯示出 Fiber 與 ipyparallel 相比具有更好的可伸縮性。
結論
Fiber 是一個新的 Python 分布式庫,現已開源。我們設計它是為了讓用戶能夠在一個計算機集群上輕松地實現大規模計算。實驗表明,Fiber 實現了我們的許多目標,包括有效地利用大量的異構計算硬件,動態地伸縮算法以提高資源使用效率,以及減少在計算機集群上運行復雜算法所需的工程負擔。
我們希望,Fiber 將進一步加快解決工程難題的進展,使開發方法并大規模地運行以了解其好處變得更容易。要了解更多細節,請查看Fiber GitHub 庫。
查看英文原文:
https://eng.uber.com/fiberdistributed/
總結
以上是生活随笔為你收集整理的Uber正式开源分布式机器学习平台Fiber的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求不该歌词。
- 下一篇: 王者荣耀里边的原画是谁画的呢?