博客專欄

EEPW首頁 > 博客 > 大模型有什么用,從技術(shù)上看

大模型有什么用,從技術(shù)上看

發(fā)布人:CV研究院 時間:2023-04-18 來源:工程師 發(fā)布文章
一、大模型有什么用

目前為止,大模型主要是以NLP為主,因為NLP拋棄了RNN序列依賴的問題,采用了Attention is All you need的Transformer結(jié)構(gòu),使得NLP能夠演變出更多大模型。圖像領域也不甘示弱,CNN大模型也開始陸續(xù)涌現(xiàn)。

  1. 模型碎片化,大模型提供預訓練方案。目前AI面對行業(yè)、業(yè)務場景很多,人工智能需求正呈現(xiàn)出碎片化、多樣化的特點。從開發(fā)、調(diào)參、優(yōu)化、迭代到應用,AI模型研發(fā)成本極高,且難以滿足市場定制化需求,所以網(wǎng)上有的人會說現(xiàn)階段的AI模型研發(fā)處于手工作坊式。基本上一個公司想要用AI賦能自身的業(yè)務,多多少少也得招聘懂AI的研發(fā)人員。為了解決手工作坊式走向工廠模式,大模型提供了一種可行方案,也就是“預訓練大模型+下游任務微調(diào)”的方式。大規(guī)模預訓練可以有效地從大量標記和未標記的數(shù)據(jù)中捕獲知識,通過將知識存儲到大量的參數(shù)中并對特定任務進行微調(diào),極大地擴展了模型的泛化能力。例如,在NLP領域,預訓練大模型共享了預訓任務和部分下游任務的參數(shù),在一定程度上解決了通用性的難題,可以被應用于翻譯,問答,文本生成等自然語言任務。PS:手工作坊式 ==> 工廠模式,一個大模型替代之前幾十個專門小模型。

  2. 大模型具備自監(jiān)督學習功能,降低訓練研發(fā)成本。大模型的自監(jiān)督學習方法,可以減少數(shù)據(jù)標注,在一定程度上解決了人工標注成本高、周期長、準確度不高的問題。

  3. 大模型有望進一步突破現(xiàn)有模型結(jié)構(gòu)的精度局限。從深度學習發(fā)展前10年的歷程來看,模型精度提升,主要依賴網(wǎng)絡在結(jié)構(gòu)上的變革。例如,從AlexNet到ResNet50,再到NAS搜索出來的EfficientNet,ImageNet Top-1 精度從58提升到了84。但是,隨著神經(jīng)網(wǎng)絡結(jié)構(gòu)設計技術(shù),逐漸成熟并趨于收斂,想要通過優(yōu)化神經(jīng)網(wǎng)絡結(jié)構(gòu)從而打破精度局限非常困難。近年來,隨著數(shù)據(jù)規(guī)模和模型規(guī)模的不斷增大,模型精度也得到了進一步提升,研究實驗表明,模型和數(shù)據(jù)規(guī)模的增大確實能突破現(xiàn)有精度的一個局限。

二、什么是大模型

TensorFlow在推薦系統(tǒng)中的分布式訓練優(yōu)化實踐隨著美團業(yè)務的發(fā)展,推薦系統(tǒng)模型的規(guī)模和復雜度也在快速增長,具體表現(xiàn)如下:

  1. 訓練數(shù)據(jù):訓練樣本從到百億增長到千億,增長了近10倍。

  2. 稀疏參數(shù):個數(shù)從幾百到幾千,也增長了近10倍;總參數(shù)量(也就是tf.Variable)從幾億增長到百億,增長了10~20倍。

  3. 模型復雜度:越來越復雜,模型單步計算時間增長10倍以上。對于大流量業(yè)務,一次訓練實驗,從幾個小時增長到了幾天,而此場景一次實驗保持在1天之內(nèi)是基本的需求。

深度學習分布式訓練的現(xiàn)狀及未來大模型主要分為兩類:

  1. 搜索、推薦、廣告類任務,它的特點是海量樣本及大規(guī)模稀疏參數(shù)(sparse embeddings),適合使用 CPU/GPU 參數(shù)服務器模式(PS);參數(shù)服務器模式從第一代 Alex Smola 在 2010 年提出的 LDA(文本挖掘領域的隱狄利克雷分配模型),到第二代 Jeff Dean 提出的 DistBelief,接著到第三代李沐提出的相對成熟的現(xiàn)代 Parameter Server 架構(gòu),再到后來的百花齊放:Uber 的 Horvod,阿里的 XDL、PAI,Meta 的 DLRM,字節(jié)的 BytePs、美團基于 Tensorlow 做的各種適配等等。參數(shù)服務器的功能日趨完善,性能也越來越強,有純 CPU、純 GPU,也有異構(gòu)模式。

  2. CV、NLP 任務,它的特點是常規(guī)樣本數(shù)據(jù)及大規(guī)模稠密參數(shù),它適合用純 GPU 集合通信模式(Collective)?;诩?GPU 的集合通信模式的分布式訓練框架,伴隨著 Nvidia 的技術(shù)迭代,特別是 GPU 通信技術(shù)(GPU Direct RDMA)的進步,性能也變得愈來愈強。

廣告推薦中大規(guī)模分布式模型 為啥一兩百類的特征,我們卻總是聽說大規(guī)模特征?舉個例子,用戶 userid 這一維特征,比如系統(tǒng)中用戶有1億個,那么每個 id 實際上也可以當做一個獨立的特征對待。這樣一算,特征規(guī)模就上去了。這里就要重新理解 embedding 的概念了。對于模型而言,id 查了embedding表后得到向量,輸入進來進行計算,是對數(shù)據(jù)進行抽特征。如果類比到圖像分類,抽取 rgb 特征來分類 (一個值變成 3個255)

參數(shù)量卷到一百萬億!華人團隊開源史上最大的推薦訓練系統(tǒng)Persia 一般來說,推薦系統(tǒng)模型首先需要將不同的ID特征(如用戶ID和session ID)映射到一個固定長度的低維向量,而系統(tǒng)中的用戶ID、交叉特征數(shù)量都特別多,就需要更大規(guī)模的模型來捕獲特征和映射。但更大規(guī)模的embedding layer也需要更大的內(nèi)存來載入,不得不說大模型太費錢了!

圖片

有了embedding后,剩下的工作就簡單了,設計后續(xù)layer來適配不同的任務。通常只占據(jù)整個模型的0.1%,無需大內(nèi)存,主要是一些計算密集型的工作。

在實現(xiàn)上

  1. 推理服務在運行時 也會訪問ps (distributed inference),根據(jù) ID feature 查詢對應的 embedding 向量。當然,有的框架直接將 ps 組件的功能內(nèi)嵌到各個worker 上了。

  2. 針對 大模型 包含 embedding layer的場景,input 層和 embedding 層之間不是全連接的,而是一個 embedding_lookup 的Op

  3. 常規(guī)的dense 模型,input是一個一維向量。針對多個id feature,為了 確保與模型的input 層對齊,input 實際變成了一個 map<string,tensor>,key 為id feature 名字,value 為id feature 值對應的 tensor。

三、大了難在哪
  1. 內(nèi)存墻。在計算過程中,神經(jīng)網(wǎng)絡模型每一層的卷積或者全連接計算,都會把權(quán)重W_m長期保存下來,用作網(wǎng)絡的權(quán)重參數(shù)更新(靜態(tài)內(nèi)存)。另外針對諸如ADAM的優(yōu)化器,會存儲優(yōu)化器的動量等信息,用于優(yōu)化器計算(動態(tài)內(nèi)存)。一塊有16G顯存的AI芯片,最大能塞滿20+億參數(shù)的模型,但是這時候已經(jīng)沒有額外空間,留給動態(tài)內(nèi)存進行分配啦。靜態(tài)內(nèi)存和動態(tài)內(nèi)存都可能造成內(nèi)存墻的問題。

  2. 通訊墻。大模型通過模型并行、流水線并行切分到AI集群后,通訊便成了主要的性能瓶頸。隨著機器規(guī)模的擴大,基于同步的All Reduce通訊聚合方式,會因為大量的AI芯片和服務器之間頻繁進行同步,出現(xiàn)水桶效應,也就是最慢的一路通訊,將會決定整個AI集群的通訊的高度。如果采用目前比較流行的Ring-AllReduce的通信聚合方式,當通訊的環(huán)越大,通訊的延長將會不斷地被擴大。另外網(wǎng)絡協(xié)議的多次握手的方式,諸如此類的開銷會導致訓練無法有效利用帶寬。

  3. 性能墻。性能墻呢主要是指計算資源利用率的問題。隨著大模型的提出,對算力需求更加迫切,理論上在4K的集群上每塊卡快1分鐘,總體就快了68個小時。大模型會增加對算力的需求,但是隨著大模型引入各項分布式并行技術(shù)的同時,會降低計算資源的利用率。

    1. 算子層(Operator Level):小算子過多,可以通過算子融合進行優(yōu)化;子實現(xiàn)不夠高效,類似于卷積CONV算子針對2x2和3x3 Kernel大小的使用Winograd算法代替;內(nèi)存局部性差,對算子和內(nèi)存的開銷進行分析,可以對計算時算子輸出有相同的shape進行復用。

    2. 圖層(Graph Level):如何搜索和切分處計算效率更高的子圖,分配到不同的機器上進行計算;數(shù)據(jù)在通訊和內(nèi)存之間如何增加overlay重疊部分,提高單卡整體的計算率。

    3. 任務層(Task Level):在任務層級,性能的瓶頸從計算轉(zhuǎn)移到了通信,如何降低通信量,縮減通信域規(guī)模,盡可能把通信時延隱藏在計算中,是大規(guī)模訓練的核心關(guān)注點。

  4. 調(diào)優(yōu)墻。所以在數(shù)千節(jié)點的集群上,需要考慮到提升算法工程師分布式調(diào)試調(diào)優(yōu)的效率,另外還要考慮降低工程師對大模型進行并行切分的難度。除了對人的考慮,還要對硬件集群的管理,需要保證計算的正確性、性能、可用性。要是有一臺機器壞了,如何快速恢復訓練中的參數(shù)。

    四、CV和NLP場景

    淺談工業(yè)界分布式訓練(一) 除了上述的數(shù)據(jù)量級大,不同場景下分布式訓練的痛點 對CV和NLP場景

    1. CV和NLP場景模型復雜,單機性能要求高,比如卷積的計算時間在CPU上和 GPU上相差十倍到幾十倍。==> 業(yè)界主要使用高性能的GPU進行計算,并采用All-reduce的通信拓撲進行參數(shù)的同步更新。

    2. 模型大(DenseNet部分),比如NLP領域,GPT-3這樣的模型高達1750億參數(shù),顯存占用高達2.8 TB,單機內(nèi)存無法容納。而Bert-Large雖然只有3.4億參數(shù)規(guī)模,但由于各種內(nèi)存占用,在16G V100上,訓練也僅能使用batch Size=8。==> 當面對GPT-3這種DenseNet部分大的模型,Allreduce 單卡內(nèi)存無法容納,我們需要采用模型并行(model parallelism)的方式將計算圖劃分到不同的設備上構(gòu)建有向無環(huán)圖(DAG)進行分布式訓練,其中Gpipe, Megatron, Oneflow和Whale都提出模型并行的相關(guān)解決方案。相比于數(shù)據(jù)并行每個worker只有一部分數(shù)據(jù),模型并行下每個node使用所有數(shù)據(jù).

      1. Intra-layer parallelism(Tensor Parallelism) 。主要是將一層Layer中的矩陣計算分別拆分到不同的機器上進行運算,比如簡單的Y_1=W_1 X_1這一次矩陣乘法中,我們將模型參數(shù)W_1或者輸入數(shù)據(jù)X_1,按某個維度分別拆分到不同設備上計算,比如1D Megatron。

      2. Inter-layer parallelism(Pipeline Parallelism)。而Inter-Layer Parallism會將模型的layers拆分到不同的機器上,則一次forward就需要跨過不同的機器串行地進行運算,而流行并行通過將batch size切分為更小的mirco batch,減少數(shù)據(jù)依賴,從而將整個計算過程異步起來,最大化資源利用率。舉例來說,在一個簡單的三層MLP中(的Y_i = W_i X_i, i=1,2,3)會存在三次矩陣乘法 W_i X_i,流水線并行會把W_i X_i分別分配到三臺機器上進行運算。

    AI for Science的出現(xiàn),讓高性能計算與AI融合成為剛需:

    1. 數(shù)據(jù)并行。假如整個模型設兩個節(jié)點,一個模型節(jié)點0、另一個模型做的節(jié)點1,整個模型都做了數(shù)據(jù)并行,數(shù)據(jù)各一半要拿去訓練學習,但是要注意訓練完了以后不是最終的結(jié)果,因為只輸入了一半的數(shù)據(jù)。因此這中間要AII-Reduce

    2. 模型并行。將整個模型切成一半,一半模型節(jié)點0,一半模型節(jié)點1,數(shù)據(jù)是整個拿去訓練。訓練完了以后出來的結(jié)果也不是最終結(jié)果,因為只訓練了一半的模型,出來還有AII-Gather,也是做通信的。 究竟用哪種并行方法呢?實際上這跟計算機結(jié)構(gòu)有關(guān)。如果每臺計算機之間通信都非???,那么用數(shù)據(jù)并行就可以;如果你的通信比較慢,就要考慮模型并行。因此,這些模型如何跟數(shù)據(jù)、機器實際情況匹配?這就涉及到軟硬件協(xié)

    五、模型保存

    基于tensorflow做擴展支持大模型的做法

    1. 在模型比較小的時候,比如100G以下,模型還有可能單機存儲。這個時候的方案是tensorflow分布式訓練+savedmodel,分布式訓練可以用多個ps(tensorflow自帶的),資源管理可以用yarn。用分布式是由于樣本數(shù)大,同時多ps也能異步加速訓練。saved_model一般由chief worker保存,但存下來以后,會抹掉ps的痕跡,保存的模型跟單機訓練的一模一樣。

    2. 當模型比較大的時候,這個時候要求的樣本數(shù)也更大,訓練完dump出來的模型會很大,一個單機放不下,尤其是embedding table。這個時候怎么辦?一個自然的思路就是,把訓練時候的ps拷貝同步一份給serving ps,線上由該ps做serving。注意后面談到的serving ps,都是自己開發(fā)或者根據(jù)某個開源軟件修改而成(比如ps-lite)。如果是天級模型,可以用tensorflow原生的worker和train ps,但依然用saved model方式把模型存放到hdfs,然后從hdfs讀入另外一個serving ps。如果是實時訓練,則serving ps還得跟訓練ps進行實時的網(wǎng)絡連接,在內(nèi)存就解決掉weight同步的處理,這個時候就不能用tensorflow原生的ps了,因為原生的ps沒有實現(xiàn)同步接口。ps變了,worker也得跟著變,worker大多數(shù)都是基于tensorflow的c++底層接口開發(fā),底層用到tf的session接口。

    六、解決思路

    針對上述的問題,各個大廠的訓練框架進行很多相關(guān)優(yōu)化,目前總結(jié)下來,核心的兩點,一個在于分布式通信拓撲的設計,還有一個在于Embedding Lookup的性能優(yōu)化。

    只要單卡放的下,走數(shù)據(jù)并行,ps 或allreduce 都行,allreduce 通信成本小一些。若規(guī)模變大

    1. 稀疏模型,稀疏參數(shù)特殊處理

      1. 使用ps,加上一些稀疏tensor 的優(yōu)化,且將 embedding 存儲和更新 負擔轉(zhuǎn)嫁到 ps

      2. 稠密參數(shù)allreduce,想辦法解決 稀疏tensor 的存儲、通信成本。比如 HybridBackend架構(gòu)中參數(shù)放在 worker 上:稠密參數(shù) replication 存放,每個 worker 都有副本,梯度更新時進行 allreduce;稀疏參數(shù) partition 存放,每個 worker 只有部分分片,梯度更新時進行 alltoall。allreduce 和 alltoall 都會使用 nccl 進行同步通信,效率較高。hb 進行 alltoall 時,通信的是稀疏梯度,而不是完整的參數(shù),通信量上和 ps 是一致的,但是通信效率會更高。


    1. 稠密模型,單卡無論如何也放不下了,就只能采取模型并行 及附屬的一些優(yōu)化方案

    知乎高贊回答——為什么說大模型訓練很難?

    1. 算子拆分 單個矩陣乘法可以分到兩個device上計算 Y = WX = [W1,W2]X = [W1X,W2X]。我們在工程上要做的就是:將切分到兩個device上,將復制到兩個device上,然后兩個device分別做矩陣乘法即可。有的時候,切分會帶來額外的通信,比如矩陣乘法切到了reduction維度上,為了保持語義正確,就必須再緊跟一個AllReduce通信。這里復雜之處在于,你不能無腦地將所有算子全部做拆分,因為拆分可能會引入一些額外通信,降低總體吞吐。所以你得做些分析,決定哪些算子被拆分,現(xiàn)在大部分框架都不支持這種全自動化策略,要么是半自動或純手工,要么是針對某種模型把它的拆分方案寫死。所以只能造輪子解決這個事

    2. 流水并行 不切算子,而是將不同的Layer切分到不同的Device上,就可以形成Pipeline方案,GPipe就是這樣一種方案,提出了將一個batch拆分成若干個micro-batch,依次推入到Pipeline系統(tǒng)中,即可消除Bubble time。和算子拆分類似,全自動化方案工作量不小,比如Pipeline怎么切,才能讓通信量小,計算還能均勻,這需要一定的算法和工程量

    搞定大模型訓練

    我們的模型可能會很大,或者數(shù)據(jù)量會很大。僅僅用一塊GPU卡可能連模型都放不下,或者batch size只能設置的很小,但是我們知道有些情況下大的batch size往往會提供更好的效果。

    1. 假設我們只有一個GPU,我們的模型一次只能輸入batch size為8的數(shù)據(jù),那么我們怎么樣實現(xiàn)batch size為32的更新呢?那就需要時間換空間了,即我們訓練32/8=4步才去更新模型,也就是所謂的梯度累積。

    2. Gradient-Checkpointing, 那么如果你的GPU連batch size為1都跑不了怎么辦?我們在訓練深度學習模型的時候,需要先做前向傳播,然后將中間得到的激活值存儲在內(nèi)存中,然后反向傳播的時候再根據(jù)loss和激活值計算梯度。也就是說內(nèi)存消耗其實跟模型的層數(shù)線性相關(guān)。那么怎么減少這個內(nèi)存消耗呢?最簡單的想法就是我不存這些中間信息,計算梯度的時候,到了某一層我重新計算它的激活值,這個方法雖然可以讓內(nèi)存消耗是個常量,但是運行時間會是O(n^2),這是沒法接受的。那么就有一個折中的辦法,我不存全部的中間數(shù)據(jù),只存部分,那么我們在計算梯度的時候不需要從頭計算了,只需要從最近的checkpoint點計算就好。

    3. 我們訓練模型一般都是用單精度(FP32)的參數(shù),但是其實我們還使用半精度(FP16)。半精度可以降低內(nèi)存消耗,從而訓練更大的模型或者使用更大的batch size;同時運算時間受內(nèi)存和算術(shù)帶寬的限制,在有些gpu(Tensor cores)上可以為半精度提供更大的算術(shù)帶寬,從而提高訓練效率,減少inference用時。

      轉(zhuǎn)自知乎《大模型有什么用,從技術(shù)上看》


    *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



    關(guān)鍵詞: AI

    相關(guān)推薦

    技術(shù)專區(qū)

    關(guān)閉