Uber正式開源分佈式機器學習平臺:Fiber

做者 | Jiale Zhi,Rui Wang,Jeff Clune,Kenneth O. Stanley
譯者 | 平川
策劃 | 陳思
Uber 開發了 POET、Go-Explore 和 GTN 等算法,這些算法利用大量的計算來訓練神經網絡模型。爲了使將來幾代相似算法的大規模計算成爲可能,Uber 進而開發了一種新的分佈式計算庫 Fiber,它能夠幫助用戶輕鬆地將本地計算方法擴展到成百上千臺機器上。Fiber 可使使用 Python 的大規模計算項目變得快速、簡單和資源高效,從而簡化 ML 模型訓練過程,並得到更優的結果。

本文最初發佈於 Uber 工程博客,由 InfoQ 中文站翻譯並分享。python

Fiber:Uber 的開源分佈式機器學習平臺,圖片由 Flat UI Kit 提供,項目地址:https://github.com/uber/fibergit

在過去的幾年中,計算機不斷加強的處理能力推進了機器學習的進步。算法愈來愈多地利用並行性,並依賴分佈式訓練來處理大量數據。然而,隨之而來的是增長數據和訓練的需求,這對管理和利用大規模計算資源的軟件提出了巨大的挑戰。github

在 Uber,咱們開發了 POET、Go-Explore 和 GTN 等算法,這些算法利用大量的計算來訓練神經網絡模型。爲了使將來幾代相似算法的大規模計算成爲可能,咱們開發了一種新的分佈式計算庫 Fiber,它能夠幫助用戶輕鬆地將本地計算方法擴展到成百上千臺機器上。Fiber 可使使用 Python 的大規模計算項目變得快速、簡單和資源高效,從而簡化 ML 模型訓練過程,並得到更優的結果。算法

大規模分佈式計算的挑戰

在理想狀況下,將運行在一臺機器上的應用程序擴展爲運行在一批機器上的應用程序應該很容易,只需更改命令行參數便可。然而,在現實世界中,這並不容易。編程

咱們天天都與許多運行大規模分佈式計算任務的人一塊兒工做,咱們發現,如今很難利用分佈式計算的緣由有如下幾個:後端

  • 在筆記本或臺式機本地運行代碼與在生產集羣上運行代碼之間存在着巨大的差距。 你可讓 MPI 在本地運行,但在計算機集羣上運行它是徹底不一樣的過程。微信

  • 不能動態擴展。若是你啓動了一個須要大量資源的做業,那麼你極可能須要等待,直到全部資源都分配好了才能夠運行該做業。這個等待下降了擴展的效率。網絡

  • 錯誤處理缺失。在運行時,有些做業可能會失敗。你可能不得不還原部分結果或整個地放棄本次運行。架構

  • 學習成本很高。每一個系統都有不一樣的 API 和編程約定。要使用新系統啓動做業,用戶必須學習一套全新的約定。app

新的 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 Gym Bipedal 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://github.com/uber/fiber

查看英文原文:

https://eng.uber.com/fiberdistributed/


推薦閱讀

Uber開放源代碼「 Manifold」:用於機器學習的可視化調試工具


點擊「閱讀原文」圖書配套資源

本文分享自微信公衆號 - 相約機器人(xiangyuejiqiren)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索