大模型有什么用,從技術(shù)上看
目前為止,大模型主要是以NLP為主,因?yàn)镹LP拋棄了RNN序列依賴的問(wèn)題,采用了Attention is All you need的Transformer結(jié)構(gòu),使得NLP能夠演變出更多大模型。圖像領(lǐng)域也不甘示弱,CNN大模型也開始陸續(xù)涌現(xiàn)。
模型碎片化,大模型提供預(yù)訓(xùn)練方案。目前AI面對(duì)行業(yè)、業(yè)務(wù)場(chǎng)景很多,人工智能需求正呈現(xiàn)出碎片化、多樣化的特點(diǎn)。從開發(fā)、調(diào)參、優(yōu)化、迭代到應(yīng)用,AI模型研發(fā)成本極高,且難以滿足市場(chǎng)定制化需求,所以網(wǎng)上有的人會(huì)說(shuō)現(xiàn)階段的AI模型研發(fā)處于手工作坊式?;旧弦粋€(gè)公司想要用AI賦能自身的業(yè)務(wù),多多少少也得招聘懂AI的研發(fā)人員。為了解決手工作坊式走向工廠模式,大模型提供了一種可行方案,也就是“預(yù)訓(xùn)練大模型+下游任務(wù)微調(diào)”的方式。大規(guī)模預(yù)訓(xùn)練可以有效地從大量標(biāo)記和未標(biāo)記的數(shù)據(jù)中捕獲知識(shí),通過(guò)將知識(shí)存儲(chǔ)到大量的參數(shù)中并對(duì)特定任務(wù)進(jìn)行微調(diào),極大地?cái)U(kuò)展了模型的泛化能力。例如,在NLP領(lǐng)域,預(yù)訓(xùn)練大模型共享了預(yù)訓(xùn)任務(wù)和部分下游任務(wù)的參數(shù),在一定程度上解決了通用性的難題,可以被應(yīng)用于翻譯,問(wèn)答,文本生成等自然語(yǔ)言任務(wù)。PS:手工作坊式 ==> 工廠模式,一個(gè)大模型替代之前幾十個(gè)專門小模型。
大模型具備自監(jiān)督學(xué)習(xí)功能,降低訓(xùn)練研發(fā)成本。大模型的自監(jiān)督學(xué)習(xí)方法,可以減少數(shù)據(jù)標(biāo)注,在一定程度上解決了人工標(biāo)注成本高、周期長(zhǎng)、準(zhǔn)確度不高的問(wèn)題。
大模型有望進(jìn)一步突破現(xiàn)有模型結(jié)構(gòu)的精度局限。從深度學(xué)習(xí)發(fā)展前10年的歷程來(lái)看,模型精度提升,主要依賴網(wǎng)絡(luò)在結(jié)構(gòu)上的變革。例如,從AlexNet到ResNet50,再到NAS搜索出來(lái)的EfficientNet,ImageNet Top-1 精度從58提升到了84。但是,隨著神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)技術(shù),逐漸成熟并趨于收斂,想要通過(guò)優(yōu)化神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)從而打破精度局限非常困難。近年來(lái),隨著數(shù)據(jù)規(guī)模和模型規(guī)模的不斷增大,模型精度也得到了進(jìn)一步提升,研究實(shí)驗(yàn)表明,模型和數(shù)據(jù)規(guī)模的增大確實(shí)能突破現(xiàn)有精度的一個(gè)局限。
二、什么是大模型
TensorFlow在推薦系統(tǒng)中的分布式訓(xùn)練優(yōu)化實(shí)踐隨著美團(tuán)業(yè)務(wù)的發(fā)展,推薦系統(tǒng)模型的規(guī)模和復(fù)雜度也在快速增長(zhǎng),具體表現(xiàn)如下:
訓(xùn)練數(shù)據(jù):訓(xùn)練樣本從到百億增長(zhǎng)到千億,增長(zhǎng)了近10倍。
稀疏參數(shù):個(gè)數(shù)從幾百到幾千,也增長(zhǎng)了近10倍;總參數(shù)量(也就是tf.Variable)從幾億增長(zhǎng)到百億,增長(zhǎng)了10~20倍。
模型復(fù)雜度:越來(lái)越復(fù)雜,模型單步計(jì)算時(shí)間增長(zhǎng)10倍以上。對(duì)于大流量業(yè)務(wù),一次訓(xùn)練實(shí)驗(yàn),從幾個(gè)小時(shí)增長(zhǎng)到了幾天,而此場(chǎng)景一次實(shí)驗(yàn)保持在1天之內(nèi)是基本的需求。
深度學(xué)習(xí)分布式訓(xùn)練的現(xiàn)狀及未來(lái)大模型主要分為兩類:
搜索、推薦、廣告類任務(wù),它的特點(diǎn)是海量樣本及大規(guī)模稀疏參數(shù)(sparse embeddings),適合使用 CPU/GPU 參數(shù)服務(wù)器模式(PS);參數(shù)服務(wù)器模式從第一代 Alex Smola 在 2010 年提出的 LDA(文本挖掘領(lǐng)域的隱狄利克雷分配模型),到第二代 Jeff Dean 提出的 DistBelief,接著到第三代李沐提出的相對(duì)成熟的現(xiàn)代 Parameter Server 架構(gòu),再到后來(lái)的百花齊放:Uber 的 Horvod,阿里的 XDL、PAI,Meta 的 DLRM,字節(jié)的 BytePs、美團(tuán)基于 Tensorlow 做的各種適配等等。參數(shù)服務(wù)器的功能日趨完善,性能也越來(lái)越強(qiáng),有純 CPU、純 GPU,也有異構(gòu)模式。
CV、NLP 任務(wù),它的特點(diǎn)是常規(guī)樣本數(shù)據(jù)及大規(guī)模稠密參數(shù),它適合用純 GPU 集合通信模式(Collective)?;诩?GPU 的集合通信模式的分布式訓(xùn)練框架,伴隨著 Nvidia 的技術(shù)迭代,特別是 GPU 通信技術(shù)(GPU Direct RDMA)的進(jìn)步,性能也變得愈來(lái)愈強(qiáng)。
廣告推薦中大規(guī)模分布式模型 為啥一兩百類的特征,我們卻總是聽(tīng)說(shuō)大規(guī)模特征?舉個(gè)例子,用戶 userid 這一維特征,比如系統(tǒng)中用戶有1億個(gè),那么每個(gè) id 實(shí)際上也可以當(dāng)做一個(gè)獨(dú)立的特征對(duì)待。這樣一算,特征規(guī)模就上去了。這里就要重新理解 embedding 的概念了。對(duì)于模型而言,id 查了embedding表后得到向量,輸入進(jìn)來(lái)進(jìn)行計(jì)算,是對(duì)數(shù)據(jù)進(jìn)行抽特征。如果類比到圖像分類,抽取 rgb 特征來(lái)分類 (一個(gè)值變成 3個(gè)255)
參數(shù)量卷到一百萬(wàn)億!華人團(tuán)隊(duì)開源史上最大的推薦訓(xùn)練系統(tǒng)Persia 一般來(lái)說(shuō),推薦系統(tǒng)模型首先需要將不同的ID特征(如用戶ID和session ID)映射到一個(gè)固定長(zhǎng)度的低維向量,而系統(tǒng)中的用戶ID、交叉特征數(shù)量都特別多,就需要更大規(guī)模的模型來(lái)捕獲特征和映射。但更大規(guī)模的embedding layer也需要更大的內(nèi)存來(lái)載入,不得不說(shuō)大模型太費(fèi)錢了!
有了embedding后,剩下的工作就簡(jiǎn)單了,設(shè)計(jì)后續(xù)layer來(lái)適配不同的任務(wù)。通常只占據(jù)整個(gè)模型的0.1%,無(wú)需大內(nèi)存,主要是一些計(jì)算密集型的工作。
在實(shí)現(xiàn)上
推理服務(wù)在運(yùn)行時(shí) 也會(huì)訪問(wèn)ps (distributed inference),根據(jù) ID feature 查詢對(duì)應(yīng)的 embedding 向量。當(dāng)然,有的框架直接將 ps 組件的功能內(nèi)嵌到各個(gè)worker 上了。
針對(duì) 大模型 包含 embedding layer的場(chǎng)景,input 層和 embedding 層之間不是全連接的,而是一個(gè) embedding_lookup 的Op
常規(guī)的dense 模型,input是一個(gè)一維向量。針對(duì)多個(gè)id feature,為了 確保與模型的input 層對(duì)齊,input 實(shí)際變成了一個(gè) map<string,tensor>,key 為id feature 名字,value 為id feature 值對(duì)應(yīng)的 tensor。
內(nèi)存墻。在計(jì)算過(guò)程中,神經(jīng)網(wǎng)絡(luò)模型每一層的卷積或者全連接計(jì)算,都會(huì)把權(quán)重W_m長(zhǎng)期保存下來(lái),用作網(wǎng)絡(luò)的權(quán)重參數(shù)更新(靜態(tài)內(nèi)存)。另外針對(duì)諸如ADAM的優(yōu)化器,會(huì)存儲(chǔ)優(yōu)化器的動(dòng)量等信息,用于優(yōu)化器計(jì)算(動(dòng)態(tài)內(nèi)存)。一塊有16G顯存的AI芯片,最大能塞滿20+億參數(shù)的模型,但是這時(shí)候已經(jīng)沒(méi)有額外空間,留給動(dòng)態(tài)內(nèi)存進(jìn)行分配啦。靜態(tài)內(nèi)存和動(dòng)態(tài)內(nèi)存都可能造成內(nèi)存墻的問(wèn)題。
通訊墻。大模型通過(guò)模型并行、流水線并行切分到AI集群后,通訊便成了主要的性能瓶頸。隨著機(jī)器規(guī)模的擴(kuò)大,基于同步的All Reduce通訊聚合方式,會(huì)因?yàn)榇罅康腁I芯片和服務(wù)器之間頻繁進(jìn)行同步,出現(xiàn)水桶效應(yīng),也就是最慢的一路通訊,將會(huì)決定整個(gè)AI集群的通訊的高度。如果采用目前比較流行的Ring-AllReduce的通信聚合方式,當(dāng)通訊的環(huán)越大,通訊的延長(zhǎng)將會(huì)不斷地被擴(kuò)大。另外網(wǎng)絡(luò)協(xié)議的多次握手的方式,諸如此類的開銷會(huì)導(dǎo)致訓(xùn)練無(wú)法有效利用帶寬。
性能墻。性能墻呢主要是指計(jì)算資源利用率的問(wèn)題。隨著大模型的提出,對(duì)算力需求更加迫切,理論上在4K的集群上每塊卡快1分鐘,總體就快了68個(gè)小時(shí)。大模型會(huì)增加對(duì)算力的需求,但是隨著大模型引入各項(xiàng)分布式并行技術(shù)的同時(shí),會(huì)降低計(jì)算資源的利用率。
算子層(Operator Level):小算子過(guò)多,可以通過(guò)算子融合進(jìn)行優(yōu)化;子實(shí)現(xiàn)不夠高效,類似于卷積CONV算子針對(duì)2x2和3x3 Kernel大小的使用Winograd算法代替;內(nèi)存局部性差,對(duì)算子和內(nèi)存的開銷進(jìn)行分析,可以對(duì)計(jì)算時(shí)算子輸出有相同的shape進(jìn)行復(fù)用。
圖層(Graph Level):如何搜索和切分處計(jì)算效率更高的子圖,分配到不同的機(jī)器上進(jìn)行計(jì)算;數(shù)據(jù)在通訊和內(nèi)存之間如何增加overlay重疊部分,提高單卡整體的計(jì)算率。
任務(wù)層(Task Level):在任務(wù)層級(jí),性能的瓶頸從計(jì)算轉(zhuǎn)移到了通信,如何降低通信量,縮減通信域規(guī)模,盡可能把通信時(shí)延隱藏在計(jì)算中,是大規(guī)模訓(xùn)練的核心關(guān)注點(diǎn)。
調(diào)優(yōu)墻。所以在數(shù)千節(jié)點(diǎn)的集群上,需要考慮到提升算法工程師分布式調(diào)試調(diào)優(yōu)的效率,另外還要考慮降低工程師對(duì)大模型進(jìn)行并行切分的難度。除了對(duì)人的考慮,還要對(duì)硬件集群的管理,需要保證計(jì)算的正確性、性能、可用性。要是有一臺(tái)機(jī)器壞了,如何快速恢復(fù)訓(xùn)練中的參數(shù)。
淺談工業(yè)界分布式訓(xùn)練(一) 除了上述的數(shù)據(jù)量級(jí)大,不同場(chǎng)景下分布式訓(xùn)練的痛點(diǎn) 對(duì)CV和NLP場(chǎng)景
CV和NLP場(chǎng)景模型復(fù)雜,單機(jī)性能要求高,比如卷積的計(jì)算時(shí)間在CPU上和 GPU上相差十倍到幾十倍。==> 業(yè)界主要使用高性能的GPU進(jìn)行計(jì)算,并采用All-reduce的通信拓?fù)溥M(jìn)行參數(shù)的同步更新。
模型大(DenseNet部分),比如NLP領(lǐng)域,GPT-3這樣的模型高達(dá)1750億參數(shù),顯存占用高達(dá)2.8 TB,單機(jī)內(nèi)存無(wú)法容納。而Bert-Large雖然只有3.4億參數(shù)規(guī)模,但由于各種內(nèi)存占用,在16G V100上,訓(xùn)練也僅能使用batch Size=8。==> 當(dāng)面對(duì)GPT-3這種DenseNet部分大的模型,Allreduce 單卡內(nèi)存無(wú)法容納,我們需要采用模型并行(model parallelism)的方式將計(jì)算圖劃分到不同的設(shè)備上構(gòu)建有向無(wú)環(huán)圖(DAG)進(jìn)行分布式訓(xùn)練,其中Gpipe, Megatron, Oneflow和Whale都提出模型并行的相關(guān)解決方案。相比于數(shù)據(jù)并行每個(gè)worker只有一部分?jǐn)?shù)據(jù),模型并行下每個(gè)node使用所有數(shù)據(jù).
Intra-layer parallelism(Tensor Parallelism) 。主要是將一層Layer中的矩陣計(jì)算分別拆分到不同的機(jī)器上進(jìn)行運(yùn)算,比如簡(jiǎn)單的Y_1=W_1 X_1這一次矩陣乘法中,我們將模型參數(shù)W_1或者輸入數(shù)據(jù)X_1,按某個(gè)維度分別拆分到不同設(shè)備上計(jì)算,比如1D Megatron。
Inter-layer parallelism(Pipeline Parallelism)。而Inter-Layer Parallism會(huì)將模型的layers拆分到不同的機(jī)器上,則一次forward就需要跨過(guò)不同的機(jī)器串行地進(jìn)行運(yùn)算,而流行并行通過(guò)將batch size切分為更小的mirco batch,減少數(shù)據(jù)依賴,從而將整個(gè)計(jì)算過(guò)程異步起來(lái),最大化資源利用率。舉例來(lái)說(shuō),在一個(gè)簡(jiǎn)單的三層MLP中(的Y_i = W_i X_i, i=1,2,3)會(huì)存在三次矩陣乘法 W_i X_i,流水線并行會(huì)把W_i X_i分別分配到三臺(tái)機(jī)器上進(jìn)行運(yùn)算。
AI for Science的出現(xiàn),讓高性能計(jì)算與AI融合成為剛需:
數(shù)據(jù)并行。假如整個(gè)模型設(shè)兩個(gè)節(jié)點(diǎn),一個(gè)模型節(jié)點(diǎn)0、另一個(gè)模型做的節(jié)點(diǎn)1,整個(gè)模型都做了數(shù)據(jù)并行,數(shù)據(jù)各一半要拿去訓(xùn)練學(xué)習(xí),但是要注意訓(xùn)練完了以后不是最終的結(jié)果,因?yàn)橹惠斎肓艘话氲臄?shù)據(jù)。因此這中間要AII-Reduce
模型并行。將整個(gè)模型切成一半,一半模型節(jié)點(diǎn)0,一半模型節(jié)點(diǎn)1,數(shù)據(jù)是整個(gè)拿去訓(xùn)練。訓(xùn)練完了以后出來(lái)的結(jié)果也不是最終結(jié)果,因?yàn)橹挥?xùn)練了一半的模型,出來(lái)還有AII-Gather,也是做通信的。 究竟用哪種并行方法呢?實(shí)際上這跟計(jì)算機(jī)結(jié)構(gòu)有關(guān)。如果每臺(tái)計(jì)算機(jī)之間通信都非???,那么用數(shù)據(jù)并行就可以;如果你的通信比較慢,就要考慮模型并行。因此,這些模型如何跟數(shù)據(jù)、機(jī)器實(shí)際情況匹配?這就涉及到軟硬件協(xié)
基于tensorflow做擴(kuò)展支持大模型的做法
在模型比較小的時(shí)候,比如100G以下,模型還有可能單機(jī)存儲(chǔ)。這個(gè)時(shí)候的方案是tensorflow分布式訓(xùn)練+savedmodel,分布式訓(xùn)練可以用多個(gè)ps(tensorflow自帶的),資源管理可以用yarn。用分布式是由于樣本數(shù)大,同時(shí)多ps也能異步加速訓(xùn)練。saved_model一般由chief worker保存,但存下來(lái)以后,會(huì)抹掉ps的痕跡,保存的模型跟單機(jī)訓(xùn)練的一模一樣。
當(dāng)模型比較大的時(shí)候,這個(gè)時(shí)候要求的樣本數(shù)也更大,訓(xùn)練完dump出來(lái)的模型會(huì)很大,一個(gè)單機(jī)放不下,尤其是embedding table。這個(gè)時(shí)候怎么辦?一個(gè)自然的思路就是,把訓(xùn)練時(shí)候的ps拷貝同步一份給serving ps,線上由該ps做serving。注意后面談到的serving ps,都是自己開發(fā)或者根據(jù)某個(gè)開源軟件修改而成(比如ps-lite)。如果是天級(jí)模型,可以用tensorflow原生的worker和train ps,但依然用saved model方式把模型存放到hdfs,然后從hdfs讀入另外一個(gè)serving ps。如果是實(shí)時(shí)訓(xùn)練,則serving ps還得跟訓(xùn)練ps進(jìn)行實(shí)時(shí)的網(wǎng)絡(luò)連接,在內(nèi)存就解決掉weight同步的處理,這個(gè)時(shí)候就不能用tensorflow原生的ps了,因?yàn)樵膒s沒(méi)有實(shí)現(xiàn)同步接口。ps變了,worker也得跟著變,worker大多數(shù)都是基于tensorflow的c++底層接口開發(fā),底層用到tf的session接口。
針對(duì)上述的問(wèn)題,各個(gè)大廠的訓(xùn)練框架進(jìn)行很多相關(guān)優(yōu)化,目前總結(jié)下來(lái),核心的兩點(diǎn),一個(gè)在于分布式通信拓?fù)涞脑O(shè)計(jì),還有一個(gè)在于Embedding Lookup的性能優(yōu)化。
只要單卡放的下,走數(shù)據(jù)并行,ps 或allreduce 都行,allreduce 通信成本小一些。若規(guī)模變大
稀疏模型,稀疏參數(shù)特殊處理
使用ps,加上一些稀疏tensor 的優(yōu)化,且將 embedding 存儲(chǔ)和更新 負(fù)擔(dān)轉(zhuǎn)嫁到 ps
稠密參數(shù)allreduce,想辦法解決 稀疏tensor 的存儲(chǔ)、通信成本。比如 HybridBackend架構(gòu)中參數(shù)放在 worker 上:稠密參數(shù) replication 存放,每個(gè) worker 都有副本,梯度更新時(shí)進(jìn)行 allreduce;稀疏參數(shù) partition 存放,每個(gè) worker 只有部分分片,梯度更新時(shí)進(jìn)行 alltoall。allreduce 和 alltoall 都會(huì)使用 nccl 進(jìn)行同步通信,效率較高。hb 進(jìn)行 alltoall 時(shí),通信的是稀疏梯度,而不是完整的參數(shù),通信量上和 ps 是一致的,但是通信效率會(huì)更高。
稠密模型,單卡無(wú)論如何也放不下了,就只能采取模型并行 及附屬的一些優(yōu)化方案
知乎高贊回答——為什么說(shuō)大模型訓(xùn)練很難?
算子拆分 單個(gè)矩陣乘法可以分到兩個(gè)device上計(jì)算 Y = WX = [W1,W2]X = [W1X,W2X]。我們?cè)诠こ躺弦龅木褪牵簩⑶蟹值絻蓚€(gè)device上,將復(fù)制到兩個(gè)device上,然后兩個(gè)device分別做矩陣乘法即可。有的時(shí)候,切分會(huì)帶來(lái)額外的通信,比如矩陣乘法切到了reduction維度上,為了保持語(yǔ)義正確,就必須再緊跟一個(gè)AllReduce通信。這里復(fù)雜之處在于,你不能無(wú)腦地將所有算子全部做拆分,因?yàn)椴鸱挚赡軙?huì)引入一些額外通信,降低總體吞吐。所以你得做些分析,決定哪些算子被拆分,現(xiàn)在大部分框架都不支持這種全自動(dòng)化策略,要么是半自動(dòng)或純手工,要么是針對(duì)某種模型把它的拆分方案寫死。所以只能造輪子解決這個(gè)事
流水并行 不切算子,而是將不同的Layer切分到不同的Device上,就可以形成Pipeline方案,GPipe就是這樣一種方案,提出了將一個(gè)batch拆分成若干個(gè)micro-batch,依次推入到Pipeline系統(tǒng)中,即可消除Bubble time。和算子拆分類似,全自動(dòng)化方案工作量不小,比如Pipeline怎么切,才能讓通信量小,計(jì)算還能均勻,這需要一定的算法和工程量
搞定大模型訓(xùn)練
我們的模型可能會(huì)很大,或者數(shù)據(jù)量會(huì)很大。僅僅用一塊GPU卡可能連模型都放不下,或者batch size只能設(shè)置的很小,但是我們知道有些情況下大的batch size往往會(huì)提供更好的效果。
假設(shè)我們只有一個(gè)GPU,我們的模型一次只能輸入batch size為8的數(shù)據(jù),那么我們?cè)趺礃訉?shí)現(xiàn)batch size為32的更新呢?那就需要時(shí)間換空間了,即我們訓(xùn)練32/8=4步才去更新模型,也就是所謂的梯度累積。
Gradient-Checkpointing, 那么如果你的GPU連batch size為1都跑不了怎么辦?我們?cè)谟?xùn)練深度學(xué)習(xí)模型的時(shí)候,需要先做前向傳播,然后將中間得到的激活值存儲(chǔ)在內(nèi)存中,然后反向傳播的時(shí)候再根據(jù)loss和激活值計(jì)算梯度。也就是說(shuō)內(nèi)存消耗其實(shí)跟模型的層數(shù)線性相關(guān)。那么怎么減少這個(gè)內(nèi)存消耗呢?最簡(jiǎn)單的想法就是我不存這些中間信息,計(jì)算梯度的時(shí)候,到了某一層我重新計(jì)算它的激活值,這個(gè)方法雖然可以讓內(nèi)存消耗是個(gè)常量,但是運(yùn)行時(shí)間會(huì)是O(n^2),這是沒(méi)法接受的。那么就有一個(gè)折中的辦法,我不存全部的中間數(shù)據(jù),只存部分,那么我們?cè)谟?jì)算梯度的時(shí)候不需要從頭計(jì)算了,只需要從最近的checkpoint點(diǎn)計(jì)算就好。
我們訓(xùn)練模型一般都是用單精度(FP32)的參數(shù),但是其實(shí)我們還使用半精度(FP16)。半精度可以降低內(nèi)存消耗,從而訓(xùn)練更大的模型或者使用更大的batch size;同時(shí)運(yùn)算時(shí)間受內(nèi)存和算術(shù)帶寬的限制,在有些gpu(Tensor cores)上可以為半精度提供更大的算術(shù)帶寬,從而提高訓(xùn)練效率,減少inference用時(shí)。
轉(zhuǎn)自知乎《大模型有什么用,從技術(shù)上看》
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。