(轉載:http://www.36dsj.com/archives/85383)機器學習與人工智能,相信你們已經耳熟能詳,隨着大規模標記數據的積累、神經網絡算法的成熟以及高性能通用GPU的推廣,深度學習逐漸成爲計算機專家以及大數據科學家的研究重點。近年來,不管是圖像的分類、識別和檢測,仍是語音生成、天然語言處理,甚至是AI下圍棋或者打遊戲都基於深度學習有了很大的突破。而隨着TensorFlow、Caffe等開源框架的發展,深度學習的門檻變得愈來愈低,甚至初中生均可以輕易實現一個圖像分類或者自動駕駛的神經網絡模型,但目前最前沿的成果主要仍是出自Google、微軟等巨頭企業。算法
Google不只擁有優秀的人才儲備和大數據資源,其得天獨厚的基礎架構也極大推進了AI業務的發展,得益於內部的大規模集羣調度系統Borg,開發者能夠快速申請大量GPU資源進行模型訓練和上線模型服務,而且經過資源共享和自動調度保證總體資源利用率也很高。Google開源了TensorFlow深度學習框架,讓開發者能夠在本地輕易地組合MLP、CNN和RNN等模塊實現複雜的神經網絡模型,但TensorFlow只是一個數值計算庫,並不能解決資源隔離、任務調度等問題,將深度學習框架集成到基於雲計算的基礎架構上將是下一個關鍵任務。數據庫
除了Google、微軟,國內的百度也開源了PaddlePaddle分佈式計算框架,而且官方集成了Kubernetes等容器調度系統,用戶能夠基於PaddlePaddle框架實現神經網絡模型,同時利用容器的隔離性和Kubernetes的資源共享、自動調度、故障恢復等特性,但平臺不能支持更多深度學習框架接口。而亞馬遜和騰訊雲相繼推出了面向開發者的公有云服務,能夠同時支持多種主流的開源深度學習框架,阿里、金山和小米也即將推出基於GPU的雲深度學習服務,還有無數企業在默默地研發內部的機器學習平臺和大數據服務。編程
面對如此眼花繚亂的雲服務和開源技術,架構師該如何考慮其中的技術細節,從用戶的角度又該如何選擇這些平臺或者服務呢。我將介紹小米雲深度學習平臺的架構設計與實現細節,但願能給AI領域的研發人員提供一些思考和啓示。後端
雲深度學習平臺設計api
雲深度學習平臺(Cloud Machine Learning),就是基於雲計算的機器學習和深度學習平臺。首先TensorFlow、MXNet是深度學習框架或者深度學習平臺,但並非雲深度學習平臺,它們雖然能夠組成一個分佈式計算集羣進行模型訓練,但須要用戶在計算服務器上手動啓動和管理進程,並沒有云計算中任務隔離、資源共享、自動調度、故障恢復以及按需計費等功能。所以咱們須要區分深度學習類庫以及深度學習平臺之間的關係,而這些類庫實現的隨機梯度降低和反向傳播等算法倒是深度學習應用所必須的,這是一種全新的編程範式,須要咱們已有的基礎架構去支持。數組
雲計算和大數據發展超過了整整十年,在業界催生很是多優秀的開源工具,如實現了相似AWS IaaS功能的OpenStack項目,還有Hadoop、Spark、Hive等大數據存儲和處理框架,以及近年很火的Docker、Kubernetes等容器項目,這些都是構建現代雲計算服務的基石。安全
這些雲服務有共同的特色,例如咱們使用HDFS進行數據存儲,用戶不須要手動申請物理資源就能夠作到開箱即用,用戶數據保存在幾乎無限制的公共資源池中,而且經過租戶隔離保證數據安全,集羣在節點故障或者水平擴容時自動觸發Failover且不會影響用戶業務。雖然Spark經過MLib接口提供部分機器學習算法功能,但毫不能替代TensorFlow、Caffe等深度學習框架的做用,所以咱們仍須要實現Cloud Machine Learning服務,而且確保實現雲服務的基本特性服務器
總結爲下面幾條:網絡
相比於MapReduce或者Spark任務,深度學習的模型訓練時間週期長,並且須要調優的超參數更多,平臺設計還須要考慮如下幾點:架構
這是我我的對雲深度學習平臺的需求理解,也是小米在實現cloud-ml服務時的基本設計原則。雖然涉及到高可用、分佈式等頗具實現難度的問題,但藉助目前比較成熟的雲計算框架和開源技術,咱們的架構和實現基本知足了前面全部的需求
雲深度學習平臺架構
遵循前面的平臺設計原則,咱們的系統架構也越發清晰明瞭,爲了知足小米內部的全部深度學習和機器學習需求:
計算機領域有句名言「任何計算機問題均可以經過增長一箇中間層來解決」。不管是AWS、OpenStack、Hadoop、Spark仍是TCP/IP都是這樣作的,經過增長一個抽象層來屏蔽底層資源,對上層提供更易用或者更可靠的訪問接口。小米的cloud-ml平臺也須要實現對底層物理資源的屏蔽,尤爲是對GPU資源的抽象和調度,但咱們不須要從新實現,由於社區已經有了不少成熟的分佈式解決方案,如OpenStack、Yarn和Kubernetes。目前OpenStack和Yarn對GPU調度支持有所欠缺,虛擬機也存在啓動速度慢、性能overhead較大等問題,而容器方案中的Kubernetes和Mesos發展迅速,支持GPU調度等功能,是目前最值得推薦的架構選型之一。
進一步簡化了整個雲深度學習平臺的使用流程,總體架構設計以下圖:
雲深度學習平臺實現
前面提到咱們後端使用Kubernetes編排系統,經過API Server實現受權認證和Quota配額功能。因爲雲深度學習服務是一個計算服務,和我之前作過的分佈式存儲服務有着本質的區別,計算服務離線運算時間較長,客戶端請求延時要求較低並且吞吐很小,所以咱們的API服務在易用性和高性能上能夠選擇前者,目前主流的Web服務器均可以知足需求。基於Web服務器咱們能夠實現集成內部權限管理系統的業務邏輯,小米生態雲提供了相似AWS的AKSK簽名認證機制,用戶註冊登陸後能夠自行建立Access key和Secret key,請求時在客戶端進行AKSK的簽名後發送,這樣用戶不須要把帳號密碼或密鑰加到請求中,即便密鑰泄露也能夠由用戶來禁用,請求時即便籤名被嗅探也只能重放當前的請求內容,是很是可靠的安全機制。除此以外,咱們參考OpenStack項目的體系架構,實現了多租戶和Quota功能,經過認證和受權的請求須要通過Quota配額檢查,在高可用數據庫中持久化相應的數據,這樣平臺管理員就能夠動態修改每一個租戶的Quota,並且用戶能夠隨時查看自身的審計信息。
咱們遵循Google CloudML標準,會自動生成Cluster spec等信息經過環境變量加入到容器的啓動任務中。這樣不管是單機版訓練任務,仍是幾個節點的分佈式任務,甚至是上百節點的分佈式訓練任務,cloud-ml平臺均可以經過相同的鏡像和代碼來運行,只是啓動時傳入的環境變量不一樣,在不改變任何外部依賴的狀況下優雅地實現了看似複雜的分佈式訓練功能。
除了訓練任務,Cloud Machine Learning平臺最好也能集成模型服務、開發環境等功能。
對於模型服務,TensorFlow社區開源了TensorFlow Serving項目,能夠加載任意TensorFlow模型而且提供統一的訪問接口,
而Caffe社區也提供了Web demo項目方便用戶使用。
目前Kubernetes和Mesos都實現了相似Deployment的功能,經過製做TensorFlow Serving等服務的容器鏡像,咱們能夠很方便地爲用戶快速啓動對應的模型服務。
經過對Kubernetes API的封裝,咱們在暴露給用戶API時也提供了replicas等參數,這樣用戶就能夠直接經過Kubernetes API來建立多副本的Deployment實例,而且由Kubernetes來實現負載均衡等功能。
除此以外,TensorFlow Serving自己還支持在線模型升級和同時加載多個模型版本等功能,咱們在保證TensorFlow Serving容器正常運行的狀況下,容許用戶更新分佈式對象存儲中的模型文件就能夠輕易地支持在線模型升級的功能。
對於比較小衆但有特定使用場景的深度學習框架,Cloud Macine Learning的開發環境、訓練任務和模型服務都支持Bring Your Own Image功能,也就是說用戶能夠定製本身的Docker鏡像並在提交任務時指定使用。這種靈活的設置極大地下降了平臺管理者的維護成本,咱們不須要根據每一個用戶的需求定製通用的Golden image,事實上也不可能有完美的鏡像能夠知足全部需求,用戶不一樣的模型可能有任意的Python或者非Python依賴,甚至是本身實現的私有深度學習框架也能夠直接提交到Cloud Machine Learning平臺上訓練。內測BYOI功能時,咱們還驚喜地發現這個功能對於咱們開發新的深度學習框架支持,以及提早測試鏡像升級有很是大的幫助,同時用戶本身實現的Caffe模型服務和XGBoost模型服務也能夠完美支持。
固然Cloud Machine Learning平臺還能夠實現不少有意思的功能,例如經過對線上不一樣GPU機型打label,經過NodeSelector功能能夠容許用戶選擇具體的GPU型號進行更細粒度的調度,這須要咱們暴露更底層Kubernetes API實現,這在集羣測試中也是很是有用的功能。而不管是基於GPU的訓練任務仍是模型服務,咱們都製做了對應的CUDA容器鏡像,經過Kubernetes調度到對應的GPU計算節點就能夠訪問本地圖像處理硬件進行高性能運算了。
小米cloud-ml還開放了前置命令和後置命令功能,容許用戶在啓動訓練任務前和訓練任務結束後執行自定義命令,對於不支持分佈式存儲的深度學習框架,能夠在前置命令中掛載S3 fuse和FDS fuse到本地目錄,或者初始化HDFS的Kerberos帳號,靈活的接口能夠實現更多用戶自定義的功能。
還有超參數自動調優功能,與Google CloudML相似,用戶能夠提交時指定多組超參數配置,雲平臺能夠自動分配資源起多實例並行計算,爲了支持讀取用戶自定義的指標數據,咱們實現了相似TensorBoard的Python接口直接訪問TensorFlow event file數據,並經過命令行返回給用戶最優的超參數組合。最後還有TensorFlow Application Template功能,在Cloud Machine Learning平臺上用戶能夠將本身的模型代碼公開或者使用官方維護的開源TensorFlow應用,用戶提交任務時能夠直接指定這些開源模板進行訓練,模板已經實現了MLP、CNN、RNN和LR等經典神經網絡結構,還能夠經過超參數來配置神經網絡每一層的節點數和層數,並且能夠支持任意稠密和稀疏的數據集,這樣不須要編寫代碼就能夠在雲平臺上訓練本身的數據快速生成AI模型了。
在前面的平臺設計和平臺架構後,要實現完整的雲深度學習服務並不困難,尤爲是集成了Docker、Etcd、Kubernetes、TensorFlow等優秀開源項目,組件間經過API鬆耦合地交互,須要的重複工做主要是打通企業內部權限系統和將用戶請求轉化成Kubernetes等後端請求而已,而支持標準的打包方式還可讓業務代碼在任意雲平臺上無縫遷移。
雲深度學習平臺實踐
目前小米雲深度學習平臺已經在內部各業務部門推廣使用,相比於直接使用物理機,雲服務擁有超高的資源利用率、快速的啓動時間、近乎「無限」的計算資源、自動的故障遷移、支持分佈式訓練和超參數自動調優等優勢,相信能夠獲得更好的推廣和應用。
管理GPU資源和排查GPU調度問題也是至關繁瑣的,尤爲是須要管理不一樣GPU設備和不一樣CUDA版本的異構集羣,咱們統一規範了CUDA的安裝方式,保證Kubernetes調度的容器能夠正常訪問宿主機的GPU設備。固然對於GPU資源的調度和釋放,咱們有完善的測試文檔能夠保證每個GPU均可以正常使用,根據測試需求實現的NodeSelector功能也幫忙咱們更快地定位問題。
因爲已經支持幾十個功能和十幾個深度學習框架,每次升級均可能影響已有服務的功能,所以咱們會在多節點的分佈式staging集羣進行上線演習和測試,而且實現smoke test腳本進行完整的功能性測試。服務升級須要更新代碼,可是爲了保證不影響線上業務,不管是Kubernetes仍是咱們實現的API Server都有多副本提供服務,經過高可用技術先遷移服務進行滾動升級,對於一些單機運行的腳本也經過Etcd實現了高可用的搶主機制,保證全部組件沒有單點故障。