MLsys各方向綜述

cver發表於2020-02-07

最近在試著尋找ML + sys可做的方向,發現涉及到的坑太多了,有點眼花繚亂的感覺......不如寫點東西總結一哈,幫自己理一下思路。

個人感覺MLsys不能算是一種方向,而是一種思路......比如對於system研究者來說,可以把ML作為我們開發的系統要適配的一種benchmark,就像transaction對於資料庫、某種檔案場景對於File System的意義一樣。這樣一想可做的空間就寬廣多了。就算ML哪天又進入寒冬,之前所學的技術也仍然是可持續的。傳統的system研究者也應該適應這個潮流,不能簡單的把MLsys一律歸為大水漫灌..

有很多topic我也是初次接觸,還不是很熟悉。如有錯誤還請批評指點~

1. 分散式機器學習(Distributed DNN Training)

這個又可以分為兩個方面:from ML / system perspective。安利一下劉鐵巖老師的《分散式機器學習》這本書([ch_]表示引用這本書中的一些章節),還有UCB cs294 19fall的這一節。

ML

從ML的角度做,主要是發明或改進分散式訓練演算法[ch4] [ch5],保證在分散式加速的同時,仍然能達到原來的學習效果(loss/accuracy)。因此很多工作也被投在像ICML、NIPS這種專業ML會議上。主要用到的方法包括最佳化(optimization)和統計學習理論(statistical learning theory)。

還有一類工作涉及到如何把單機演算法改造成分散式[ch9],比如同步/非同步SGD等。這裡主要涉及到的問題是如何降低分散式環境下的通訊開銷,提高加速比。

這方面瞭解不多就少寫點了... 可以參考這裡。

System

還有一個就是從System的角度做。從分散式計算的角度來看,可以把相關工作分為以下幾類:

  1. 對於計算量太大的場景(計算並行),可以多執行緒/多節點平行計算,多節點共享公共的儲存空間。常用的一個演算法就是同步隨機梯度下降(synchronous stochastic gradient descent),含義大致相當於K個(K是節點數)mini-batch SGD [ch6.2]

  2. 對於訓練資料太多,單機放不下的場景(資料並行,也是最主要的場景),需要將資料劃分到多個節點上訓練。每個節點先用本地的資料先訓練出一個子模型,同時和其他節點保持通訊(比如更新引數)以保證最終可以有效整合來自各個節點的訓練結果,並得到全域性的ML模型。[ch6.3]

  3. 對於模型太大的場景,需要把模型(例如NN中的不同層)劃分到不同節點上進行訓練。此時不同節點之間可能需要頻繁的sync。這個叫做模型並行。[ch6.4]

  4. Pipeline Parallelism:這是去年(SOSP19 PipeDream)才出現的概念,參考這裡的第90、95頁 以及這裡的簡介。Pipeline Parallelism相當於把資料並行和模型並行結合起來,把資料劃分成多個chunk,也把訓練模型的過程分成了Forward Pass和Backward Pass兩個stage。然後用流水線的思想進行計算。

另外,分散式ML本質上還是分散式系統嘛,所以像傳統分散式系統裡的一些topic(比如一致性、fault tolerance、通訊、load balance等等)也可以放到這個背景下進行研究。

最近挖的比較多的坑大致涉及以下幾個點:

1.1. 分散式ML系統設計

[ch7.3] 最著名的就是幾大分散式DL模型:Parameter Server / AllReduce等。

個人感覺這裡面一個可以挖的坑是Decentralized Training。地裡一位大佬也在做這個方向。

1.2 Edge Computing

很多ML模型是需要在手機上執行的(比如毀圖秀秀)。針對這一場景,一個是要對手機這種低功耗裝置對ML model進行裁剪加速(後面會提到),還有一個要做的就是執行在多個device上的分散式ML。

這裡有個最近非常火的概念:Federated Learning。其實本質還是炒資料並行的冷飯...不過應用場景比較不一樣。FL更多是為了Privacy的考慮,而分散式加速訓練在這裡倒是個次要目標。FL還涉及到了模型聚合[ch8],也就是如何把多個device本地訓練出的模型合併到一起。

1.3 大量計算資源的Scheduling / device placement

UCB的CS294 19spring對這一節有過介紹。

這裡的計算資源的數量級是很大的......比如工業界會有萬臺CPU伺服器 / 上千臺GPU伺服器搭建的DL平臺。這個小方向要解決的問題就是如何充分利用它們的效能。比如在阿里PAI組的JD裡就有這麼一條:“設計探索高效的分散式Placement演算法,以更系統化的方式來解決大規模深度學習高效訓練的問題”。

這方面比較早的工作大概是這篇paper,說的是如何為TensorFlow計算圖裡的不同運算元分配不同的device,最後用強化學習實現了這個目標。這個工作看起來有點prototype,但提出了一個新的思路。

另外還有很多猛如虎的類似Train XX model in y minutes的工作。這種就不僅是placement好就能完成的了,還需要涉及系統拓撲的設計、降低communication開銷等等。

1.4 communication相關

[ch3.5] [ch7]介紹了一些宏觀上的通訊模型,但深入進去還有很多可搞的坑。傳統搞網路/分散式系統的組比較契合這個小方向。

例如我校的分散式組原來有一些geo-distributed system的工作,現在也可以往ML上裝。

1.5 其他sys for ML可做的坑

工業界的一個ML pipeline不僅僅是訓練,還涉及到很多其他的坑。這些是目前被挖的還比較少的:

  • 儲存 / Data Management:


    • 1) 訓練資料的規模是很大的。如何為ML設計一個專用的檔案系統(類似大資料界的HDFS)或者資料庫來加速讀資料呢?類似的工作有管理ML model的ModelDB.

    • 2) 在ML framework中,以及Parameter Server中,需要用一個KV storage system來儲存引數。可不可以針對ML的場景最佳化這個KV儲存系統呢?關於這個可以參考neopenx大神的blog。


2. 深度學習模型壓縮/加速

這方面和architecture結合比較緊密。CS229有這一節,也可以參考NIPS19上的這個talk。

對DL model進行壓縮主要考慮兩個角度:減少計算量(例如conv層的計算量) / 記憶體佔用(NN的引數數量)。不僅要考慮ML上的metric,也要考慮system層面的performance(例如latency / throughput / 功耗。有時候這些比ML模型的accuracy還重要)。具體的方式大概有以下幾種:

  • 1. Architectural Compression


    • Layer Design -> Typically using factorization techniques to reduce storage and computation

    • Pruning(剪枝) -> Eliminating weights, layers, or channels to reduce storage and computation from large pre-trained models. 減少卷積核大小 / 通道數等等

  • 2. Weight Compression


    • Low Bit Precision Arithmetic -> Weights and activations are stored and computed using low bit precision

    • Quantized(量化) Weight Encoding -> Weights are quantized and stored using dictionary encodings.

很多相關的工作是在ML的角度來壓縮模型的(也就是Arch Compression,特別是針對CNN和RNN。比如很著名的MobileNet)。這裡我們先(kan)略(bu)過(dong),來看從System的角度是如何加速的。

2.1 透過Quantized(量化)降低計算精度要求

量化的含義是將卷積層(the weights and / or activations of a CNN)通常要用到的32位浮點數用更低位的數來表示,如int32, int16, int8等等,來降低資源佔用(float32無論是計算還是儲存都是很吃資源的..)。量化之後無疑會損失一部分精度,但神經網路對噪聲並不是特別敏感,因此控制好量化的程度之後對ML任務的影響可以很小。

一種常用的量化方法是train in floating point and then quantize the resulting weights,訓練時還是用float32(因為要涉及到反向傳播和梯度下降,全是int就很難搞了..),但在inference的階段就可以加速啦。一個直觀的方法是事先找好一般網路引數的min / max值,然後將訓練好的網路引數乘一個scala factor來對映到[MIN_INT, MAX_INT]區間內的整數存起來。在inference時先按int來計算,最後結果再轉換回float32。這一過程中其實加速了大量的卷積計算。比如這篇paper就實現了float32到int8的量化。

混合精度計算:上面講的方法是用在inference階段的,其實在模型訓練時也可以用類似的方法來加速,只不過再用int就不大行了。一種比較新的方法是用float16(也就是俗稱的半精度),fp16佔用空間是單精度(fp32)的一半,雙精度(double,也就是fp64)的1/4。

量化的具體實現方法可以參考這裡。NVIDIA專門推出了針對inference階段量化加速的工具包TensorRT

2.2 新硬體 / DL Acclerator

在純硬體方面針對DL workload的工作也有很多,這裡來看幾個parallel相關的技術。最近Data-Level Parallelism不僅在深度學習中,在其他一些領域(比如資料庫)也有了越來越多的應用。

  • CPU:儘管GPU已經成了深度學習計算的標配,有時候仍然是需要CPU運算的。例如要在手機等辣雞裝置上進行inference。


    • SIMD:SIMD的含義是同一條指令在多個資料流上操作,和在向量處理器中一樣。在具體實現中(例如SSE指令集)是把一個128位SSE暫存器(這是新增加的SIMD專用暫存器,和早期借用FPU暫存器的MMX不同。在SSE指令集中是增加了8個這種暫存器)劃分成4個塊,同時存放4個float32單精度浮點數,4個塊可以同時進行運算(有多個運算單元,作用於不同的地址),這樣就提高了並行度。後來的SSE2 / SSE3 / SSE4 / AVX指令集在此基礎上又增加對float64 / 更多運算的支援,以及擴充套件了SIMD專用暫存器的位數,但本質上還是一樣的。  另外,SIMD帶來的並行和超標量處理器的並行性(一個週期issue多個指令,用於instruction level parallelism)不是一個概念。非超標量處理器也可以SIMD,而超標量處理器可以更並行issue多個SIMD操作。

    • VLIW:和一次issue多條指令,然後靠硬體進行ILP排程(也叫動態多發射。需要硬體實現亂序執行、分支預測等操作)的超標量處理器不同,VLIW(Very Large Instruction Width,採用這種技術的處理器也叫做靜態多發射處理器)的含義是一次只issue一條可以完成多個操作的複雜長指令(也叫發射包,其實從軟體的角度看是多條指令的集合)。因此一條指令的位寬可以很大。VLIW是透過編譯器來進行指令級並行排程的(比如一個常用的方法是迴圈展開,透過識別出可並行的重疊跨迴圈體指令塊來實現ILP)。VLIW的本意是希望在編譯階段就識別出程式中的依賴關係(靜態排程),得到可以並行執行的發射包,硬體只需要根據排程好的發射包直接執行即可,這樣就簡化了硬體實現,從而實現更大寬度發射包的並行執行。intel Itanium的IA64指令集就使用了這個技術,但它在當年並沒有取得成功。一個重要的原因是它只適合計算密集、演算法固定可控的workload。傳統的通用應用程式可能很難具備這個屬性(有很多run-time才能確定的值,另外cache訪問也是不確定的),但深度學習任務具備這些性質。

  • GPU:GPU的本質可以看做SIMT(Single Instruction Multiple Threads)。


    • 等8205課上講完GPGPU的topic再補充吧...

    • GPU叢集:

  • 系統結構:這個和純計算關係不是很大,可能暫時和ML加速也沒啥關係(事實上目前在計算機網路研究中用的還多一些)......但對於最佳化整體效能會有幫助


    • NUMA:當單個CPU效能已經到瓶頸時,多處理器就成了比較好的解決方案。為了方便程式設計,需要保證能為應用程式提供跨越所有處理器的單一實體地址空間,這種也叫做共享記憶體處理器(Shared Memory Processor)。SMP又可以分為兩種型別:1) 任何處理器訪問任何地址的仿存時間都是相同的,叫做統一儲存訪問(Uniform Memory Access)。2) 對於每個核心,訪問某些字會比訪問其他字快一些,整個記憶體空間被分割並分配給不同處理器 / 記憶體控制器,這叫做非統一儲存訪問(NonUniform Memory Access,NUMA)。NUMA雖然看起來複雜,但可以支援更大的規模(更多的核心),並且訪問附近的儲存器時具有較低的延遲。在過去記憶體控制器還在北橋的時代,多處理器用的是UMA(所有處理器都透過FSB匯流排連線北橋,再訪問記憶體)。後來隨著核心越來越多,為提高訪存速度,記憶體處理器被做到了CPU內,每個CPU有(或者很少的幾個核心共享)一個記憶體控制器,然後直連一部分記憶體空間,這些核心就被歸為一個NUMA node。而跨NUMA node之間的記憶體訪問需要走QPI匯流排。可以參考這裡的圖解。在一些涉及many core的工作中會經常用到NUMA的概念

    • RDMA:在網路環境中會用到。RDMA全稱是Remote Direct Memory Access,用於實現不需要OS參與的遠端記憶體訪問(因為message passing through kernel會浪費本來很大的記憶體和網路頻寬)。具體的技術細節可以參考這裡。

  • 專用硬體:CPU效能太菜,GPU又太龐大,於是人們開發了AI專用晶片

    • FPGA:全稱是Field Programmable Gate Array,是可以多次燒寫的。因為本質上屬於軟體所以可以快速開發 / 迭代。

    • ASIC:全稱是application-specific integrated circuits,出廠後電路就不可以改變了(需要流片)。但是效能比FPGA高。

2.3 矩陣運算元最佳化

神經網路中的很多運算本質上就是對矩陣運算,因此可以用一些矩陣乘法最佳化方案來加速。比如cublas就是封裝好的針對矩陣和向量運算的加速庫,而對於神經網路加速則會使用cudnn

運算元最佳化是個非常貼近hardware的工作,對多種裝置都人工調優這些運算元其實是比較難的...如果能簡化一部分工作就最好啦。於是就有了下面會提到的深度學習編譯器

2.4 AutoML

這個嚴格來說可能不算MLsys了...但它的思路在很多MLsys問題中也會被用到

AutoML最早只能調很有限的幾種引數,用的方法也比較暴力(啟發式搜尋)。後來能調的東西越來越多,方法也更加猛如虎...一個里程碑是NAS,標誌著神經網路結構也可以Auto了。

常用的調參方法大致可以分為這幾種:

  1. 隨機搜尋,或者說叫啟發式搜尋。包括 GridSearch 和 RandomSearch。這種方法的改進空間主要體現在使用不同的取樣方法生成配置,但本質上仍然是隨機試驗不同的配置,沒有根據跑出來的結果來反饋指導取樣過程,效率比較低。

  2. Multi-armed Bandit。這種方法綜合考慮了“探索”和“利用”兩個問題,既可以配置更多資源(也就是取樣機會)給搜尋空間中效果更優的一部分,也會考慮嘗試儘量多的可能性。Bandit 結合貝葉斯最佳化,就構成了傳統的 AutoML 的核心。

  3. 深度強化學習強化學習在 AutoML 中最著名的應用就是 NAS,用於自動生成神經網路結構。另外它在 深度學習引數調優 中也有應用。它的優點是從“從資料中學習”轉變為“從動作中學習”(比如某個引數從小調到大),既可以從效能好的樣本中學習,也可以從效能壞的樣本中學習。但強化學習的坑也比較多,體現在訓練可能比較困難,有時結果比較難復現。

之所以把AutoML也列出來,是因為這些方法在下面提到的ML for system問題中會很有用。比如之前做過的AutoTiKV就應用了一種貝葉斯最佳化方法來調節資料庫引數

cs294中給出了幾個可提高的方向:

  • Accelerate data collection and preparation


    •   Automatic data discovery

    •   Distributed data processing, esp. for image and video data

    •   Data cleaning and schema driven auto-featurization

  • Accelerate model selection and hyper-parameter search


    •   Parallel and distributed execution

    •   Data and feature caching across training runs

  • Provenance


    •   Track previous model development to inform future decisions

    •   Connect errors in production with decisions in model development


3. 深度學習框架/系統設計

和Distributed Training的區別是這裡更關注一些工程上的東西(框架設計、API設計等等)。一個Deep Learning Framework大致需要以下幾個元素:

  • 支援各種運算元(op) 和 tensor (data)

  • 計算圖的定義方式(動態 v.s. 靜態)

  • Auto Diff

  • Optimizer(例如Adam)

  • 各種加速和最佳化的庫:cudnn, openblas,mkl等

3.1 Deep Learning Framework

這一節重點關注這幾個方向:

  • Differentiable Programming:如果用過Keras或者PyTorch就會記得它可以簡單得像搭積木一樣摞一個NN出來,只需要定義一個一個的層(前向傳播邏輯)和損失函式就行了。而NN的訓練需要Backward Propagation / Forward Propagation,也就是計算微分,運算時framework可以根據定義好的計算圖自動求導算梯度。只要可微分就可以保證這個積木能摞出來,然後使用鏈式法則就可以自動計算微分(Automatic Differentiation)。如果一個語言或者framework具備了Differentiable Programming的性質,就可以更簡單的在它上面開發Deep Learning應用(可以類比python手寫NN和Keras的區別)。這篇文章對Auto Diff的實現做了很詳細的介紹。

  • Embedded Domain Specific Languages:DSL的概念我們都知道,比如SQL就是資料庫系統中的DSL,但這已經相當於一個全新的語言了。Embedded DSL是在現有語言上(例如Python)針對某個特定任務做的擴充套件。比如為了讓Python做矩陣計算更方便發明了numpy;為了進行機器學習就有了TensorFlow / PyTorch等等。Embedded DSL的作用是完成 Linear Algebra -> Pipelines -> Differentiable Programs 的轉化。

  • 根據計算圖的定義方式,可以分為Declarative Abstraction(Embedded DSL先生成靜態計算圖,類似編譯執行 define-and-run,例如Tensorflow、Caffe)和Imperative(Embedded DSL生成動態計算圖並直接輸出結果,類似解釋執行 define-by-run,例如PyTorch、Tensorflow Eager)

對於具體的DL框架來說,雖然很多公司都開始自研框架了,但最流行的基本就TensorFlow、PyTorch、mxnet等等那幾家了。不過最近又出現了分散式強化學習框架Ray,也具有很好的落地潛能。

3.2 Inference / Model Serving

之前關注了很多訓練ML模型中會遇到的問題。但實際應用場景裡,inference(直接使用訓練好的模型predict)的次數會比training多很多,因此inference的效能也很重要。

Inference可以再分為以下兩種:

  • Offline: Pre-Materialize Predictions:所有可能的query都是已知的,就事先predict好存起來。一般沒有這麼玩的...

  • Online: Compute Predictions on the fly:根據使用者的輸入實時predict。這才是最常見的場景

一個典型的ML inference pipeline大致涉及到以下工序:

  • input data

  • -> Preprocessing(比如圖片要resize)

  • -> model prediction(有時候會同時用很多model,還要ensemble起來)

  • -> 輸出結果,有時候還要處理一下

這個pipeline的衡量指標包括Latency、Throughput等(和傳統的system問題一樣呀)。cs294裡列出了幾個最近的工作,可以參考這裡的paper解讀。個人感覺這裡可做的坑不多....大多是修修補補...

3.3深度學習編譯器

這裡值得提一下TVM。這篇文章對TVM進行了非常詳細的介紹。

簡單的說TVM是在把訓練好的ML model部署在不同裝置上時用的,重點關注的是Inference而不是Training(也就是推理引擎)。在這一過程中,模型本身可能用了不同的framework來寫(比如tensorflow / PyTorch / MXNet,本質區別在於使用的運算元型別可能不一樣),而要部署到的裝置也可能有不同的硬體架構(比如x86 / ARM / GPU / FPGA)。inference的過程也就是將framework X寫出來的model放在硬體Y上執行的過程,這一過程和編譯器是非常相似的(將語言X寫的程式編譯到硬體Y上執行),這也就是深度學習編譯器的含義。

為了設計一個高效的深度學習編譯器,TVM借鑑了傳統編譯器LLVM的設計思想:抽象出編譯器前端[ 高階語言C/java -> IR ],編譯器中端[ 最佳化IR,這種是不同編譯器平臺共享的 ],編譯器後端[ IR -> 目標硬體上的binary ]等概念,引入IR (Intermediate Representation。深度學習問題中可以將計算圖作為IR,稱為Graph IR)。這樣不同硬體/framework都對標同一套IR,就避免了需要對每種硬體和framework排列組合適配的問題。TVM主要解決的是後端的問題[在目標硬體上高效執行IR]。而前端的問題[生成和最佳化IR]就交給深度學習框架們完成(針對這一步,在TVM stack中提供了NNVM,作用是represent workloads from different frameworks into standardized computation graphs)。

TVM是和硬體深度整合的,也就是需要針對每種硬體平臺實現相關的AI運算元(類似NVIDIA GPU上的cuDNN)。然而人工調優這些運算元的實現是很費精力的(特別是要針對不同形狀的業務模型),這裡面也有一些knob需要調整。為了讓這個過程也能ML化,於是後來有了AutoTVM。

cs294 sp19還提出了幾個可能的future work:

  • - Compilers are great at Ahead of Time scheduling, what about Just-In-Time scheduling?

  • - Any way we can share GPU in predictable way and maximize utilization for DNN inference?

  • - Can we optimize for “fitness” of the kernel when it’s executed along with other kernels instead of its latency?


4. 用ML最佳化傳統的system問題

這裡面的花樣就更多了...在上學期Jon的ML system課上有過較詳細的接觸。大部分是用ML去最佳化一個傳統system問題中,一些需要人工經驗調整、或者說可以從歷史情況learn到一些東西的模組。比如資料庫引數作業系統頁表、資料庫索引等等。一個模組可以被ML化的前提是它必須是empirical的,參考它在頁表(OS的工作集原理)、資料庫(DBA是個很吃經驗的活...)中的應用。如果人工都看不出來啥規律就別指望它能ML了...

一般認為用ML最佳化system的思想是起源於Jeff Dean在NIPS2017的workshop。這方面的工作很多發表在純system的頂級會議以及下屬的AI for xxx workshop上,另外一些AI會議的workshop也會收錄一些這方面的工作,比如nips 2018的MLsys workshop。從2017年開始已經有很多坑被做過了,但個人感覺還是有一些搞頭的。感覺可以從下面兩個角度再來搞:

  • 同樣的scenario,使用更合適的ML演算法。注意這裡是更合適,而不是更高大上猛如虎。


    • 比如這篇ML+Database的paper,使用了LSTM來預測未來的workload pattern,還要用GPU訓練,但生產環境上要求資料庫伺服器也安個顯示卡是不現實的。工程上的一個解決方案是搞個集中式的訓練叢集(類似OtterTune),在DBaaS的情況下這種方法倒是行得通,但在對外發布的資料庫產品中就不行了。

    • 這裡感覺可以參考早期AutoML的一些工作,因為它們本質是很類似的(都是調參嘛...)。傳統方法有啟發式搜尋/貝葉斯最佳化。最近也有很多人用強化學習去搞,但還是存在太吃資源的問題...

    • 這方面對ML知識的要求高一點。

  • 尋找system界更多可以ML化的場景。這個更適合專業的system researcher來做,對ML倒是略有了解即可。


    • 有一類思路是把ML深度整合到系統設計中,比如Andy在2019年的15-721課上提到過Self-Driving Database的概念,和之前用ML最佳化資料庫的工作不同的是,Self-Driving DB更關注如何把ML和DB深度整合,而不是搞一個又一個外掛的模組了。

    • 另外一個類似的工作是在OS領域:engineering.purdue.edu/ 。


5. 其他

方向不是很契合就先不看了...等用到了再填坑

  • ML pipeline / lifecycle:ucbrise.github.io/cs294

  • Privacy:ucbrise.github.io/cs294


需要的技能樹

這是從一些公司ML System Research Scientist崗位的招聘要求中整理出來的,更側重system一些。

System:

  • 工程基礎:C/C++、OO programming。閱讀原始碼是個很好的學習方式

  • OS

  • 分散式系統

  • 編譯原理。特別是編譯器最佳化技術、LLVM、memory optimization。Parser之類不喜歡也可以不看

  • Computer Architecture。另外還需要了解:1.GPU架構,例如視訊記憶體分配機制、CPU與GPU互動。2.CPU、儲存系統相關的新技術。3.有條件可以瞭解下深度學習專用硬體。

  • 常見的平行計算框架,例如MPI/OpenMP/CUDA

  • ML framework的底層原理,扒原始碼

  • 工業界的一些新東西:例如k8s、KubeFlow、ElasticDL

ML:

  • 機器學習基礎

  • 常見的分散式機器學習演算法、DL模型壓縮、模型加速方法(根據具體方向而定)

  • 數理基礎不要太菜…不要被人吐槽像沒學過高中數學…

CVer
CVer

一個專注於計算機視覺方向的平臺。涉及目標檢測,影像分割,目標跟蹤,人臉檢測&識別,姿態估計,GAN和醫療影像等。

相關文章