「萬(wàn)字干貨」深度對話(huà)Quentin Anthony:GPU不足,如何優(yōu)雅地訓練大模型?
在初創(chuàng )公司甚至VC都在瘋狂囤積GPU的狂熱年代,干一件事比囤GPU更有價(jià)值——搞明白如何高效地使用它們。
(資料圖片)
直到Eleuther AI的出現。
四月,Eleuther AI團隊發(fā)布博文《Transformers Math 101》,介紹如何運用簡(jiǎn)單算式估計大模型的算力成本,大大消除了該領(lǐng)域的信息不對稱(chēng),在圈內圈外廣泛傳播,成為該領(lǐng)域最具權威性的博文之一。公式如下:
C = τT?≈?6PD
其中:C表示Transformer需要的計算量,單位是FLOP;P表示Transformer模型包含的參數量;D表示訓練數據規模,以Token數量為單位;τ表示吞吐量,單位為FLOP 表示訓練時(shí)間;
該公式的原理如下:
C=Cforward+Cbackward:表示訓練過(guò)程中的前后向傳播;?Cforward?≈?2PD:前向傳播計算成本約等于兩倍的參數量乘以數據規模;Cbackrward?≈?4PD:反向傳播計算成本約等于四倍的參數量乘以數據規模;
C是一個(gè)量化計算成本的單位,通常用FLOP表示,亦可用一些新的單位來(lái)表示,如FLOP/s-s:表示每秒浮點(diǎn)運算數/秒;PetaFLOP/s-days:表示實(shí)際情況下每秒浮點(diǎn)運算數/天。
8月17日,Eleuther AI首席工程師、《Transformers Math 101》的主要作者Quentin Anthony博士,同風(fēng)險投資公司Decibel Partners 的合伙人兼首席技術(shù)官Alessio、Latent Space主理人Swyx進(jìn)行了一場(chǎng)深度交流,
雙方圍繞Transformer模型算力評估、混合精度訓練、3D并行、INT8量化、分布式挑戰等NLP前沿話(huà)題展開(kāi)了深度討論,文章干貨很足,相信對想了解Transformer成本、大模型優(yōu)化技術(shù)等方面的朋友一定大有裨益。
以下為全文內容,大家enjoy~???
(由ChatGPT翻譯,經(jīng)略微修改)
●?發(fā)文動(dòng)機
●?GPU并非越多越好
●?估計GPT-3訓練的計算量
●?AMD GPU:可用,但效率不高
●?模型精度(FP32、FP16、BF16等)對內存的影響
●?深度學(xué)習模型量化的好處
●?如何計算優(yōu)化器的內存使用
●?訓練內存的各個(gè)組成部分
● 并行訓練
●?高級3D并行技術(shù)
●?異構集群分布的挑戰
01 發(fā)文動(dòng)機
Quentin:
聊到撰寫(xiě)《Transformer Math 101》一文的動(dòng)機,就不得不提到我經(jīng)常會(huì )在深度學(xué)習訓練領(lǐng)域看到一些推特帖子,比如Hugging Face的Stas Bekman,他會(huì )發(fā)布一些推文,說(shuō)什么他們剛剛發(fā)現了一個(gè)神奇數字,一切都變得快了20%等等。
他們非常興奮,但實(shí)際上并不真正了解發(fā)生了什么。對我們來(lái)說(shuō),我們經(jīng)常發(fā)現很多人可能了解AI訓練或推理的理論或基本原理,但沒(méi)有人真正了解像在自己的機器上如何正確運行分布在兩個(gè)GPU上的推理之類(lèi)的細節。
而我們,在Eleuther內部積累了很多筆記,并在工程師之間共享,我們認為,這可能會(huì )幫助很多其他人。
這可能不適合寫(xiě)論文,但對于博客文章或技術(shù)報告來(lái)說(shuō),這可能確實(shí)能夠從已有的硬件中擠出更多性能。
因此,我們在Eleuther有很多經(jīng)驗,我們試圖以一種大公司們不會(huì )采取的方式將其與人們分享。
Swyx:
是的,這是很少有人會(huì )真正干的事情。首先,寫(xiě)下來(lái)需要額外的工作。其次,這是一種商業(yè)機密,因此很少有人這樣做。
因此,通常了解這些內容的唯一方法就是實(shí)際在大型模型實(shí)驗室中工作。而你們,做了很多特別的事情。我唯一能想到的其他另一個(gè)情況是Facebook的OPT。還有什么類(lèi)似的項目,可以共享交流經(jīng)驗,但不是正式的研究知識呢?
Quentin:
我會(huì )說(shuō)是Bloom。比如Hugging Face的Bloom項目在大科學(xué)領(lǐng)域等方面,這種開(kāi)放程度非常高。
我覺(jué)得,OPT和Bloom的級別相同,甚至更詳細。
除此之外,我想微軟有一個(gè)有關(guān)他們的Turing NLG的文檔。他們的文章讀起來(lái)非常輕松,也確實(shí)談到了工作中的一些挑戰。除了OPT, Bloom和我們,我想不出其他的了。這是一個(gè)新事物。
Swyx:
重要的是,你們正追求足夠好的經(jīng)驗法則。我認為,很多人試圖追求精確,但過(guò)于精確實(shí)際上并不有幫助。
Quentin:
是的,你會(huì )在博客文章中看到一些類(lèi)似表述。你知道,我們不會(huì )進(jìn)一步詳細討論每個(gè)小的內存部分,錙銖必較的話(huà)可能需要額外的一個(gè)月。但是,得到足夠好的結果對人們仍然有幫助。
02 最少GPU數量,是最佳方案
Alessio:
聊回您在《Transformer Math 101》一文中給出的估計方程,這里的核心方程式不是計算成本,而是轉化Transformer模型所需的計算,大約等于τ乘以T,其中τ是吞吐量,單位為FLOPT表示訓練時(shí)間,然后T是花費的時(shí)間。
我認為人們可以很容易地想象這一點(diǎn)?;旧鲜悄阌卸嗌賯€(gè)GPU,你讓它們運行多長(cháng)時(shí)間。
之前在Chinchilla論文和OpenAI的規模定律中,有類(lèi)似的內容,你在博文中也提到了這一點(diǎn)。
現在,人們在構建模型時(shí)應該如何考慮這個(gè)問(wèn)題?當他們開(kāi)始考慮訓練自己的基于Transformer 的模型時(shí),他們應該從哪里找到這個(gè)方程?
Quentin:
人們通常從數據集開(kāi)始,你有一些數據集,然后你想在基于此訓練一個(gè)模型。
讓我們開(kāi)始逐步思考,一開(kāi)始,從6PD的角度來(lái)看,每個(gè)參數大約有6個(gè)令牌與之對應。因此,這決定了我的模型大小,以此為Chinchilla Optimal。
從那時(shí)起,我們發(fā)現為了獲得良好的質(zhì)量模型,需要更多的令牌,可能會(huì )超過(guò)20個(gè)。
但從系統的角度來(lái)看,你們應該考慮的下一個(gè)問(wèn)題是,這個(gè)模型需要多長(cháng)時(shí)間來(lái)訓練?我應該有什么樣的預算?
假設我需要一些云實(shí)例,持續一段時(shí)間,每個(gè)實(shí)例都有一個(gè)附加的價(jià)格。這就是吞吐量的用武之地。
現在,你有了這個(gè)模型,這個(gè)參數數量,你應該將它映射到一個(gè)Transformer架構,并在該模型類(lèi)型的軟件棧上基準測試你的吞吐量,接著(zhù)你可以在單個(gè)GPU上實(shí)現每秒的FLOPS。
然后根據并行性方案(我相信我們會(huì )詳細討論的,例如數據并行性或張量并行性等),這個(gè)FLOPS數將如何擴展到不同數量的GPU?
從這里,你將得到一個(gè)時(shí)間。進(jìn)而,得到了時(shí)間,就能算出成本。
簡(jiǎn)而言之,這就是答案。
Alessio:
我注意到另一件事,你提到一些這些定律,只在1個(gè)小時(shí)內使用1000 GPU的成本與1個(gè)GPU運行1000小時(shí)的成本相同才成立。
考慮目前我們缺乏大量GPU的實(shí)際情況,在這方面,對于人們如何優(yōu)先考慮這一點(diǎn),你有什么想法嗎?
我會(huì )說(shuō),首先應該找出剛好能容納你的模型的最小GPU數量。
如果您在訓練一個(gè)相當大的模型,內存瓶頸是你最大的問(wèn)題。如果只在訓練一個(gè)小模型,那沒(méi)人會(huì )在意。
大多數人關(guān)心的模型,都需要分配到多個(gè)GPU上。因此,找到適合你的模型的一個(gè)實(shí)例的最小gpu數量,然后計算需要多長(cháng)時(shí)間。如果是時(shí)間合理,那么你完成了。如果時(shí)間太長(cháng),那么你就需要開(kāi)始考慮使用多個(gè)模型實(shí)例。
我總是覺(jué)得,人們應該選擇最小數量的GPU。你擁有的GPU數量越多,出現問(wèn)題的可能性就越大。
所以我會(huì )說(shuō),只要找出什么時(shí)間對你來(lái)說(shuō)是合理的,然后將gpu的數量與之匹配,而不需更多。
人們往往會(huì )變得貪婪,他們會(huì )說(shuō),如果我有兩倍的GPU,我可以在半個(gè)時(shí)間內完成這項工作。但事實(shí)上,最終可能花了三倍時(shí)間,因為每天都會(huì )出現各種問(wèn)題。那時(shí),可能需要痛苦地在午夜時(shí)分起床,加班加點(diǎn)搶修你的模型。
Swyx:
你們會(huì )不會(huì )有一個(gè)類(lèi)似的開(kāi)源框架,來(lái)幫助gpu線(xiàn)性擴展?還是說(shuō),這么想過(guò)于簡(jiǎn)單化了?
Quentin:
Mosaic和我們都有一種可以理論上良好擴展的軟件堆棧配置,一會(huì )我會(huì )詳細討論。
Mosaic完全基于優(yōu)化器分片。它基于ZeRO。因此,你完全將模型優(yōu)化器、參數和梯度分布在所有不同的GPU上。你的聚合內存就是參數數目除以GPU數目。優(yōu)化器和其他內容也是一樣。
而我們在Eleuther使用了Megatron DeepSpeed的庫,會(huì )更加復雜。因此,效率可能會(huì )更高,但也更容易出現故障。
在這兩種情況下,回到實(shí)際情況,通過(guò)增加更多的GPU應該能夠獲得線(xiàn)性加速。但問(wèn)題是會(huì )出現硬件故障。
如果有太多的GPU,你可能會(huì )有問(wèn)題,例如損失會(huì )溢出,或者一個(gè)GPU掛掉,你就可能碰到軟件問(wèn)題、同步問(wèn)題等。
這就是我為什么說(shuō),實(shí)際上你應該選取你擁有的最小GPU數量,因為這些情況更容易調試。
Alessio:
另一件事情是,電腦就像在前向和后向傳遞,前向是2PD,后向是4PD。為什么兩者之間的比率是如此?你能解釋一下嗎?為什么是兩倍的數量?
Quentin:
簡(jiǎn)單來(lái)說(shuō),對于前向傳播,您只是在移動(dòng),您正在通過(guò)該層向前傳播輸入。
而在后向傳播中,你要做的事情比這更復雜一些。你正在做反向傳播。我認為我無(wú)法足夠直觀(guān)地解釋它,需要數字上進(jìn)一步深入探討。
Swyx:
實(shí)際上,反向傳播的速度很低。老實(shí)說(shuō),這是我喜歡深度學(xué)習數學(xué)的最基本的原因之一,與大學(xué)微積分中遇到的其他數值方法相比,深度學(xué)習的數學(xué)令人驚訝地高效。
Alessio:
我認為另一件事是,事情聽(tīng)起來(lái)很簡(jiǎn)單,你知道,當人們在Twitter上說(shuō),哦,20是最優(yōu)的比率,然后就是,好吧,為什么是那個(gè)數字呢?
答案通常要困難得多,就像我們現在看到的。所以我認為這是一個(gè)很好的提醒,數字聽(tīng)起來(lái)簡(jiǎn)單,就像所有最好和最受歡迎的數學(xué)方程一樣,非常優(yōu)雅。不過(guò),顯然,背后的證明并不那么容易。
02 估計GPT-3訓練的計算量
Swyx:
我想稍微測試一下這個(gè)方程。我們可以從GPT-3的角度或GPT-NeoX的角度來(lái)做。你有實(shí)際浮點(diǎn)運算和理論浮點(diǎn)運算之間的區別。
很多時(shí)候,當人們報告訓練一個(gè)模型所需的浮點(diǎn)運算量時(shí),就像我們剛剛在Lama 2中看到的那樣,估算的數值就是浮點(diǎn)運算量。
比如,GPT-3需要3.14 x 10的23次浮點(diǎn)運算。這是理論浮點(diǎn)運算。我想弄清楚一個(gè)數值是否經(jīng)得起推敲。
我想知道如何做到這一點(diǎn),因為我應該能夠將這個(gè)方程代入其中,對吧?我知道GPT-3是基于3000億tokens進(jìn)行訓練的。
我知道模型的參數大小是175。是不是只要計算一下6 x 175 x 300就行了?
Quentin:
理論浮點(diǎn)運算通常是根據給定的硬件配置得出的,這是你預計硬件可以實(shí)現的。
但問(wèn)題在于,實(shí)際上,我們通常會(huì )有一些閑置時(shí)間,例如等待從GPU到CPU的數據傳輸,或者等待跨不同GPU之間的同步。所以訓練時(shí)候你會(huì )花掉很多空閑時(shí)間。
Swyx:
聞起來(lái)怎么樣。(注:效果如何?)
Quentin:
我不確定我是否有一個(gè)自己的"聞起來(lái)怎么樣"的標準,
坦白說(shuō),也許我會(huì )查看像在A(yíng)100上期望的一些浮點(diǎn)運算量。
事實(shí)上,在某種程度上,對于給定的GPU類(lèi)型,每個(gè)人都知道可以期望多少浮點(diǎn)運算量。
例如,對于A(yíng)100來(lái)說(shuō),這個(gè)數值大約在100到180之間。對于較舊的GPU類(lèi)型V100,這個(gè)數值可能在30到40之間。
人們通常會(huì )根據運行深度學(xué)習的內核來(lái)確定應該期望的浮點(diǎn)運算量。然后,將這個(gè)與人們報告的理論浮點(diǎn)運算量進(jìn)行比較,看是否與你的預期相符。
03 A100 基線(xiàn)標準:115+ TeraFLOPS/sec
Alessio:
在文章中,你提到對于A(yíng)100來(lái)說(shuō),如果你的浮點(diǎn)運算量低于115 TeraFLOPS/秒,那么你的模型或硬件有問(wèn)題。
你是怎么得出這個(gè)115的?是不是根據實(shí)際觀(guān)察和經(jīng)驗,你在過(guò)去的幾個(gè)月里見(jiàn)到的平均水平?你是怎么得出這些數字的?
Quentin:
對于這個(gè)數字,基本上,我們比較了很多不同的框架。就像我之前提到的,Mosaic有他們自己的框架,我們也有自己的框架。它們都有自己的浮點(diǎn)運算計數器。
我們看到,在許多不同的硬件配置上,如果你正確調整設置,你應該在幾乎所有情況下都能得到超過(guò)115的浮點(diǎn)運算量。
所以,如果某個(gè)數值低于115,那么你的軟件肯定有問(wèn)題。但這實(shí)際上就是比較不同的軟件堆棧和硬件系統。
04 AMD GPU:可用,但效率不高
Alessio:
不同的GPU有什么不同嗎?
上周,我們邀請了George Hotz,他談到了AMD顯卡,以及理論上他們的浮點(diǎn)運算要比一些Nvidia顯卡好得多,但實(shí)際上,CUDA運行時(shí)會(huì )彌補這一差距。
人們應該如何考慮這一點(diǎn)?你知道,像A100的浮點(diǎn)運算量達到115 TeraFLOPS。我是否應該堅持使用它?
Quentin:
這涉及到開(kāi)發(fā)者的時(shí)間,哪個(gè)更昂貴,歸根結底,AMD和Rockham的軟件堆棧還有很長(cháng)的路要走。
我會(huì )說(shuō),大多數東西都可以在那里運行,但效率不高,而且你可能會(huì )遇到以前沒(méi)有遇到過(guò)的奇怪錯誤。
選擇使用Nvidia和PyTorch的軟件堆棧的一個(gè)重要優(yōu)點(diǎn)是,有成千上萬(wàn)個(gè)GitHub問(wèn)題與你面臨的相同問(wèn)題,而且,以開(kāi)源方式快速解決這些問(wèn)題,這可能是目前選擇Nvidia軟件堆棧的最大優(yōu)勢。
AMD的硬件與Nvidia相當,但軟件不太一樣,而且他們在開(kāi)源領(lǐng)域的勢頭還沒(méi)有完全發(fā)展起來(lái)。
例如,像Flash Attention這樣的功能在更多Nvidia GPU類(lèi)型上的應用要比在A(yíng)MD上的應用要多。等待這些最新的功能在A(yíng)MD上實(shí)現,對很多人來(lái)說(shuō)是一個(gè)障礙,但它正在發(fā)展壯大。
我現在正在A(yíng)MD上運行很多實(shí)驗,因為它已經(jīng)進(jìn)入了政府實(shí)驗室的超級計算機。所以很多實(shí)驗現在都在那里進(jìn)行,而且我預計它會(huì )在幾年內趕上來(lái)。
05 模型精度(FP32、FP16、BF16等)對內存的影響
(注:一般情況下,計算機在進(jìn)行浮點(diǎn)運算時(shí)所采用的是FP32(單精度),其中8位用于存儲整數部分,23位存儲小數部分,因此其可以存儲高精度浮點(diǎn)數。
因此,在顯存優(yōu)化場(chǎng)景下,犧牲浮點(diǎn)運算的精度可以降低存儲量。)
Alessio:
我們可以輪流討論一下,有很多內容需要涵蓋,但或許我們可以從模型權重開(kāi)始。
過(guò)去,我們在過(guò)去的許多討論中經(jīng)常涉及的一個(gè)主題就是精度和量化,這顯然是內存的主要因素之一。
你在文章中提到,大多數Transformer都是混合精度,如FP16加FP32或BF16 FP32,它們可以進(jìn)行轉換,而且可以進(jìn)行高達INT8的量化,而不會(huì )對性能造成太大的影響。也許,我們可以解釋一下一些數學(xué)和不同精度之間的字節參數比率?
Quentin:
當我開(kāi)始入行深度學(xué)習時(shí),一切都是FP32。每個(gè)參數需要32位,即4個(gè)字節。事情相當簡(jiǎn)單。你不需要進(jìn)行任何損失縮放。
但問(wèn)題是,一旦NVIDIA切換到了V100并引入了Tensor核心,FP32就不能提供太多的浮點(diǎn)運算。Tensor核心在FP16精度下執行所有計算。
因此,如果你在FP32下進(jìn)行操作,你實(shí)際上浪費了所有這些。所以一旦硬件遷移到V100,軟件就會(huì )切換到混合精度,如APEX和AMP等?;旌暇鹊囊粋€(gè)讓人意想不到的部分是,實(shí)際上在訓練時(shí)你需要更多的內存,因為你需要一個(gè)FP16版本的權重副本和一個(gè)FP32版本的權重副本。
FP16是在Tensor核心上進(jìn)行實(shí)際計算的地方。因此,你可能得到的吞吐量可能是FP32的兩倍。然后在每個(gè)步驟中,使用FP16更新FP32的副本,兩者都需要存儲在內存中。
問(wèn)題在于,FP16非常精確,但動(dòng)態(tài)范圍不太大,
因此,如果從浮點(diǎn)的角度來(lái)看,你有一個(gè)非常大的尾數,但沒(méi)有太多的指數。所以BF16將更多的位數從尾數移到指數中。也就是說(shuō),你有更大的范圍和較低的精度。
這消除了許多不穩定性問(wèn)題和損失縮放等問(wèn)題,對于任何熟悉調試的人來(lái)說(shuō),都知道它有多么不穩定,尤其是在大規模訓練中。而B(niǎo)F16則減少了很多這種問(wèn)題,但只在A(yíng)100上受支持。所以你看到了硬件和軟件之間的來(lái)回變化。
每次NVIDIA引入一些新的Tensor核心或BF16支持之類(lèi)的功能,軟件就會(huì )適應并開(kāi)始支持它,然后訓練適應。然后你現在提到了Ind8等。
現在,我們看到一些模型已經(jīng)在FP16、FP32或其他模式下訓練,然后現在你想將該模型盡可能地量化為像Ind8這樣的更小的表示,同時(shí)又保持最小的損失和精度。
實(shí)際上,我們發(fā)現,由于深度學(xué)習是一個(gè)如此具有隨機性的問(wèn)題,許多這些最后的精度位實(shí)際上并不重要,我認為這種情況將會(huì )持續下去。
06 深度學(xué)習模型量化的好處
Alessio:
如果你有一個(gè)量化成八位的模型,你只需要一個(gè)字節來(lái)表示每個(gè)參數。例如,在一個(gè)80GB VRAM的A100上,你可以放下700億個(gè)參數的八位模型,而你無(wú)法放下一個(gè)FP32模型,因為你需要大約280GB的內存。這會(huì )有多大影響?
你剛剛提到剛開(kāi)始時(shí)都是FP32,如果有一個(gè)帶有1TB VRAM的GPU,人們會(huì )只將內存加載為FP32權重嗎,還是他們仍然會(huì )希望將它們量化以使其更加高效?是的。
Quentin:
我認為,即使你有無(wú)限的VRAM,你仍然會(huì )想要一個(gè)量化模型,只是一個(gè)更大的經(jīng)過(guò)量化的模型。
因為正如我剛剛提到的,在最后,深度學(xué)習是非常隨機的,很多時(shí)候,你可能擁有世界上所有的精度,但是當你仍然非常依賴(lài)輸入時(shí),這些精度實(shí)際上是沒(méi)有意義的。你在很大程度上依賴(lài)于輸入的微小變化,也許更多的訓練數據樣本會(huì )更加重要。
在深度學(xué)習中,總體上,這些微小的精度并不是很重要的,重要的是整體的畫(huà)面。那個(gè)神經(jīng)元實(shí)際上在說(shuō)什么?而不是它可能在想什么微小的細節。我還想提到,即使你擁有A100,實(shí)際模型的大小要比你提到的要小得多。
這是因為KV緩存。所以KV緩存在推理過(guò)程中,只在推理過(guò)程中起作用,想象一下,如果你在寫(xiě)一段話(huà),你想要在寫(xiě)下一個(gè)詞之前記住之前寫(xiě)過(guò)的每一個(gè)單詞。
所以什么是自回歸語(yǔ)言建模?它就是填充下一個(gè)詞、下一個(gè)標記。如果我說(shuō)"the dog went to the",然后我需要寫(xiě)下一個(gè)詞,我可能會(huì )寫(xiě)"park"之類(lèi)的。在我寫(xiě)下一個(gè)詞之前,我的記憶會(huì )被清除,然后我必須重新閱讀整個(gè)句子。
這就是沒(méi)有KV緩存的情況。KV緩存則是說(shuō),在推理過(guò)程中,記住我之前生成的所有內容,以及我之前生成內容的所有上下文。但是KV緩存的內存開(kāi)銷(xiāo)通常與模型的內存開(kāi)銷(xiāo)相當,或在某些情況下甚至更大,特別是在上下文很長(cháng)的情況下。
我認為具體的計算公式大致是,哦,是類(lèi)似于兩倍的層數乘以頭數乘以每個(gè)頭的維度,然后有兩個(gè)這樣的部分,一個(gè)是K,一個(gè)是V。簡(jiǎn)要來(lái)說(shuō),大概就是這樣。
Alessio:
我知道,這是Transformer中的數學(xué)概念,不過(guò),關(guān)于RNNs,也有一些有趣的地方,比如遠離隨著(zhù)序列長(cháng)度增加而增加的KV緩存,而是使用固定的序列傳遞。
我知道,人們正在研究這些方面的內容。
Quentin:
那么,如何在不增加Transformer所需的二次注意力開(kāi)銷(xiāo)的情況下獲得Transformer質(zhì)量?這是有趣的,我建議人們閱讀這篇論文原文。
Swyx:
我們實(shí)際上已經(jīng)和RWKV的核心成員進(jìn)行了一次未發(fā)布的訪(fǎng)談,他們稱(chēng)之為軟注意力或輕量級注意力。我忘記他們具體叫什么了,但是可以近似地表示,使其線(xiàn)性化而不是二次方的方法。這很棒。
Quentin:
RWKV的人員經(jīng)常出現在Eleuther。
他們與我們密切合作。我的貢獻是,我們所有這些關(guān)于RNNs的實(shí)驗是由不同的人完成的,這些實(shí)驗與Transformer的關(guān)系以及我們如何將其轉化為一篇論文,以便人們不必閱讀一年前的Discord日志就能理解發(fā)生了什么。
07 如何計算優(yōu)化器的內存使用
Swyx:
很棒,現在,我想我們可能要花更多時(shí)間在優(yōu)化器狀態(tài)和Atom優(yōu)化器上。當你處理這些優(yōu)化器時(shí),你的想法是什么?在處理這些優(yōu)化器時(shí),人們應該記住什么?
Quentin:
我認為,Atom優(yōu)化器在其領(lǐng)域內是出色的。這是一個(gè)比較寬泛的問(wèn)題,所以讓我想一想。你有權重的副本,然后你有你的動(dòng)量和方差。
用直觀(guān)的預言來(lái)解釋一下動(dòng)量:比如說(shuō),你在一個(gè)峽谷,你想要到達底部。
如果你只是進(jìn)行基本的隨機梯度下降,那么每一步都會(huì )是相同大小的。而如果你使用帶有動(dòng)量項的Atom,那么你的步幅應該會(huì )逐漸變大,因為你可以看到,一般的趨勢是我們正在迅速地向下前進(jìn)。但是,由于A(yíng)tom中有所有這些額外的項,你需要更多的內存來(lái)存儲它。
例如,與SGD相比,通常需要三倍的內存。如果你在你的優(yōu)化器狀態(tài)中花費了所有這些內存,那么,你如何將它分布到GPU上?
你會(huì )發(fā)現,在給定的GPU上,實(shí)際上比起裸計算、原始的計算能力,你更多地受限于并行性。這歸結為在將模型分割成需要在許多GPU上分割之前,你能夠將多少模型放在單個(gè)GPU上。
然后,你會(huì )發(fā)現花費的時(shí)間更多地用于它們相互通信,而不是實(shí)際取得進(jìn)展。所以,我們在博文中花費了很多時(shí)間來(lái)討論如何分布你的模型?所有這些不同的分布策略是什么樣的?哪些策略更有效?考慮到很多內存都花費在了優(yōu)化器上,你如何有效地分布這個(gè)優(yōu)化器?
很多人在談?wù)摬⑿行詴r(shí),他們談?wù)摰氖悄P筒⑿行?,即參數本身。?shí)際上,在訓練時(shí),相當大一部分的內存實(shí)際上是花費在優(yōu)化器狀態(tài)上的。所以你想要深入探討其中的哪個(gè)部分嗎?你想要深入探討零、分片優(yōu)化器之類(lèi)的嗎?
Alessio:
Quentin,你在博文中提到"Atom是神奇的",實(shí)際上,即使對于像你這樣與底層很接近的人,有多少內容是實(shí)際上的"神奇",有一些東西對你來(lái)說(shuō)只是教義?有一些事情是你實(shí)際上在考慮在日常工作中進(jìn)行改進(jìn)的嗎?
Quentin:
所以我是一個(gè)系統工程師,很多這些事情對我來(lái)說(shuō)是神奇的,Atom對我來(lái)說(shuō)是神奇的。
我認為,這就是一個(gè)深度學(xué)習模型的訓練方式。這就是下一步的計算方式。然后我說(shuō),好的,如何使其變得更快?
我會(huì )說(shuō)我會(huì )看看如何通過(guò)使用第二階優(yōu)化器來(lái)改進(jìn)它。因為有很多關(guān)于這方面的研究,因為它們很難分布。
但是對我來(lái)說(shuō),核心的貢獻總是來(lái)自于其他人已經(jīng)進(jìn)行了一些深度學(xué)習的優(yōu)化,我需要使其運行得更快。所以我實(shí)際上無(wú)法談?wù)摓槭裁碅tom產(chǎn)生了,除非像我剛剛提到的,使用動(dòng)量的一些簡(jiǎn)單直觀(guān)的東西。
對我來(lái)說(shuō),Atom所占用的內存比SGD要多三倍,這一點(diǎn)很重要。所有這些內存都需要找個(gè)地方存放,它需要有效地分布。
Alessio:
所以,當你把所有這些加在一起時(shí),使用普通的Adam優(yōu)化器,每個(gè)參數需要12字節。
然后,你仍然需要在內存中保存模型參數,就像你提到的那樣,需要同時(shí)保存FB32、FB16混合量化的兩份副本,因此有不同的精度級別。所以每個(gè)參數需要6字節,對吧?
Quentin:
再回顧一下,大多數人認為模型會(huì )變得很大,所以需要純粹的模型并行處理,比如張量并行處理。
但實(shí)際上,如果我們使用FB16,模型每個(gè)參數只需要2字節。而優(yōu)化器本身需要每個(gè)參數4字節的模型狀態(tài)、4字節的動(dòng)量、4字節的方差。所以更重要的是如何高效地分割優(yōu)化器以及如何高效地存儲它。
像"bits and bytes"中的8位Adam優(yōu)化器,每個(gè)參數的優(yōu)化器狀態(tài)只需要1字節,而不是4字節之類(lèi)的。這會(huì )比將純FB16模型權重量化到int8之類(lèi)的方式,更有效地降低模型訓練所需的內存開(kāi)銷(xiāo)。
因此,對于訓練來(lái)說(shuō),優(yōu)化器內存占用非常重要,在大多數情況下最為重要。
Alessio:
在我們深入討論Zero之前,讓我們先總結一下稍后會(huì )對參數、優(yōu)化器狀態(tài)和梯度進(jìn)行分片處理??梢院?jiǎn)要談一下這個(gè)問(wèn)題,然后我們可以討論如何在GPU上高效地加載它們。
Quentin:
所謂的參數,是參數的FP32副本。
我們在優(yōu)化器討論中將它們包括在內。有些人不這樣做,但只是為了清楚起見(jiàn),優(yōu)化器狀態(tài)每個(gè)參數需要12字節,其中有四個(gè)字節是用于FP32的權重副本。
四個(gè)字節是用于動(dòng)量。我已經(jīng)解釋過(guò)為什么存儲動(dòng)量很重要,但這也是每個(gè)參數。你需要存儲該參數未來(lái)的前進(jìn)方向以及它在過(guò)去的前進(jìn)方向。
你還需要知道,我們知道它往哪走,但是在這個(gè)峽谷上會(huì )有凹陷。
所以我們需要存儲它的方差。這些凹陷的頻率是多少?我們應該更關(guān)注動(dòng)量嗎?還是這個(gè)參數在到處跳來(lái)跳去?這些都是優(yōu)化器需要存儲的重要答案,它是每個(gè)參數的。
08 訓練內存的各個(gè)組成部分(模型內存、優(yōu)化器內存、梯度內存、激活內存)
Alessio:
我正在查看總訓練內存。您實(shí)際上有模型內存、優(yōu)化器內存、梯度內存和激活內存。我認為,這是我們討論的最后一個(gè)問(wèn)題。
所以也許簡(jiǎn)要地向人們介紹一下,,比方說(shuō)活動(dòng)內存再計算、檢查點(diǎn)等。
Quentin:
在激活檢查點(diǎn)之前,可能會(huì )變得復雜,你有模型參數,就像我之前提到的一樣,它們曾經(jīng)是FP32?,F在可能是BF16,或者如果是較舊的GPU,則可能是FP16。然后有優(yōu)化器。那是許多內存所在的地方。
通常情況下,這是權重的高精度副本,通常是FP32。所以每個(gè)參數需要4字節,然后你還有一些可選項,就像我們剛剛討論過(guò)的,比如動(dòng)量或方差,或者根據你的優(yōu)化器而定的其他內容。
接著(zhù)是梯度,梯度是在模型前向傳遞后得到的梯度更新。這將是你低精度權重的副本,如果你使用FP16或BF16,每個(gè)參數需要兩個(gè)字節。
所有這些都是固定的。這個(gè)開(kāi)銷(xiāo)在訓練期間不會(huì )消失。在反向傳播梯度后,梯度可能會(huì )被清除,但優(yōu)化器狀態(tài)和模型狀態(tài)不會(huì )消失。
內存開(kāi)銷(xiāo)將一直存在。動(dòng)態(tài)的是激活再計算和激活內存。因此,有些人會(huì )遇到這樣的問(wèn)題,模型在訓練時(shí)加載得很好。但當你實(shí)際運行第一次迭代,或者運行某個(gè)未來(lái)的迭代之類(lèi)的時(shí)候,你會(huì )突然發(fā)現內存不足。這是因為你實(shí)時(shí)計算的這些激活。
Alessio:
再計算是在什么時(shí)候發(fā)生的?它是如何在重新計算和存儲之間做出決策的?
Quentin:
有很多不同的方法,但我會(huì )說(shuō)有幾種主要的方法。
首先,是一個(gè)非常簡(jiǎn)單的方案。你重新計算所有的東西。你計算出的每一個(gè)激活都會(huì )被使用或拋棄,直到結束。所以在這種情況下,你非常關(guān)心內存,但對計算關(guān)心不大。也許這會(huì )是一種情況,你必須在許多不同的GPU上分布,而且你的通信速度非常低。
然后可能是選擇性再計算。在選擇性再計算中,Megatron有一篇很好的論文,我認為我們博客文章中的圖表也是從那里來(lái)的。在這種情況下,你為每個(gè)激活做出加權決策。
對于非常大的激活張量,你決定,從內存角度來(lái)看,是將其保存更昂貴,還是從計算角度來(lái)看,重新計算更昂貴?這是Megatron實(shí)施的智能方案。
他們使用了許多不同的啟發(fā)式方法。在這里可能沒(méi)有必要提到超長(cháng)的方程式,但如果你對選擇性再計算感興趣,你應該去閱讀那篇論文。然后大多數人使用的是一個(gè)相當愚蠢的方案,包括NeoX,就是不使用所有這些啟發(fā)式方法,而是只是說(shuō),如果我的張量大于X,我就拋棄它。然后將X設置為某個(gè)固定的數字,就是這樣。
對于許多情況來(lái)說(shuō),這足夠了。
Swyx:
為什么足夠呢?
Quentin:
你不希望存儲超過(guò)X大小的張量。有些超過(guò)了這個(gè)限制,有些沒(méi)有。你不想擠壓。
你更關(guān)心的是讓某些張量盡可能地接近實(shí)際啟發(fā)式方法,而不是實(shí)際計算啟發(fā)式代碼,因為你不想花時(shí)間編寫(xiě)那些啟發(fā)式代碼。
Swyx:
好的。我想這確實(shí)為我們帶來(lái)了內存數學(xué)的一次大觀(guān)。在我們進(jìn)入分布式處理、Zero等細節之前,還有什么高層次的要點(diǎn)嗎?
Quentin:
我想大概就是這樣了。
我要說(shuō)的是,對于訓練和推斷來(lái)說(shuō),情況會(huì )大不相同。人們常常說(shuō),BF16是最好的。然而,更正確的看法是,在訓練期間,精度會(huì )更加重要。
因此,在訓練中,BF16會(huì )比在推斷中使用更久一些,因為在推斷中,模型已經(jīng)基本成型,它絕對不需要一些精度的最后幾位,因此,對于推斷來(lái)說(shuō),更容易將精度降至int8,而不是訓練。
所以,你在訓練中學(xué)到的所有東西都必須在推斷中重新學(xué)習,反之亦然。
Swyx:
還有第三類(lèi)情況。你談到了訓練與推斷之間的區別。這第三類(lèi)情況與微調和可能的參數高效微調方法有關(guān)。
實(shí)現微調的樸素方法只是進(jìn)行更多的訓練。但我不知道你是否對微調有什么直覺(jué),是否值得在這里插入。有什么直覺(jué)嗎?如果你要編寫(xiě)微調的數學(xué)公式,會(huì )包含什么內容?
Quentin:
我認為,關(guān)于微調還有很多問(wèn)題沒(méi)有得到解答。
例如,我們知道訓練的縮放規律。有些人已經(jīng)做了關(guān)于微調的縮放規律。但已經(jīng)在一個(gè)領(lǐng)域訓練過(guò)的模型如何轉移到另一個(gè)領(lǐng)域進(jìn)行微調,就微調大小而言,我們不清楚。
對于微調數據集,每個(gè)參數應該有多少個(gè)標記?也許我是無(wú)知的,但我覺(jué)得關(guān)于模型如何在原始訓練數據集中沒(méi)有的新能力進(jìn)行微調或理解的問(wèn)題,肯定會(huì )包含在未來(lái)關(guān)于微調的博客文章中。
此外,數據集轉移、學(xué)習率轉移也是我們博客感興趣的內容之一。
09 并行訓練
Alessio:
您在這里首先提到的是ZeRO,它專(zhuān)注于分片優(yōu)化器。也許可以給人們解釋一下如何理解它。
Quentin:
ZeRO圍繞兩個(gè)通信操作展開(kāi)。第一個(gè)是scatter。人們應該看一下我們有的ZeRO圖表。
在我談?wù)撨@個(gè)問(wèn)題時(shí),論文中有一個(gè)包含參數、梯度和優(yōu)化器狀態(tài)的圖表。每個(gè)GPU將獲得自己等量的切片。
如果我們進(jìn)行...有ZeRO的不同階段,但讓我們首先假設它是優(yōu)化器狀態(tài)、梯度和參數的等量切片。
在這種情況下,那將是零三,第三階段。我們通過(guò)scatter實(shí)現這一點(diǎn)。scatter的計算是,每個(gè)GPU分配1/結束的GPU數量,加上切片的偏移量,切片被分配給該GPU?,F在,所有的GPU都有一個(gè)相等的切片,按照其排名順序。
在每個(gè)訓練步驟中,該GPU將等待所有其他切片進(jìn)行通信,以便我們現在在該GPU上擁有整個(gè)數據。一旦我們有了整個(gè)數據,我們對其進(jìn)行正向傳遞。
然后,我們使用gather將該正向傳遞分發(fā)給所有其他GPU。所以,它是scatter,具體來(lái)說(shuō)是減少scatter,然后是對所有其他GPU的gather。并且您每一步都這樣做。因此,它的要點(diǎn)是您正在將這些狀態(tài)分片到不同的GPU上。
通過(guò)不同的階段,您將在圖表中看到,優(yōu)化器狀態(tài)占據了最大的比例,這是因為我之前提到的。我們包括FP32副本并進(jìn)行原子操作。所以我們需要每個(gè)參數的4個(gè)字節,用于動(dòng)量和方差。然后,零階段一,這是最常見(jiàn)的一個(gè),僅為優(yōu)化器。
零階段二是優(yōu)化器加梯度。零階段三是優(yōu)化器梯度和模型參數。但歸根結底,所有這些都是圍繞著(zhù)分片和來(lái)回聚合展開(kāi)的。所以您從ZeRO中得到了很多通信開(kāi)銷(xiāo)。但其中的正面部分是您可以將其中大部分的移動(dòng)與計算重疊。
Alessio:
Quentin:
這更多地取決于您的互連是什么。放慢一步,所有這些GPU之間都需要同步,而且這些同步往往是累積的。
因此,如果您在速度較慢的互連上使用過(guò)多的GPU,那么您最終會(huì )花更多的時(shí)間在同步上。在哪個(gè)GPU上花費更多時(shí)間同步的這個(gè)魔法數字會(huì )因您的互連和GPU內存的情況而異。每個(gè)GPU獲得多小的切片呢?
例如,對于Summit,我不能給出確切數字,但大約在200億參數左右?,F在您有200億個(gè)參數,那么對于那個(gè)數量的GPU,大約需要100到200個(gè)規模。
超過(guò)這個(gè)數量,您最終只會(huì )花費更多的時(shí)間在通信上。實(shí)際的FLOPS跌破您預先設定的某個(gè)數值,將取決于您最終確定的最佳選擇。
10 高級3D并行技術(shù)(數據、張量、流水線(xiàn))
Alessio:
那么,對我來(lái)說(shuō),這部分內容比較難理解,所以我很高興您能解釋一下3D并行。
Quentin:
好的,首先,讓我們來(lái)看一個(gè)非?;镜木S度,即數據并行。
數據并行是您有一個(gè)模型的副本。為簡(jiǎn)單起見(jiàn),假設一個(gè)副本恰好適合一個(gè)GPU。數據并行是,現在您有兩個(gè)GPU,所以GPU一上有一個(gè)副本,GPU二上有一個(gè)副本。兩者都執行正向和反向傳遞,然后進(jìn)行同步和平均梯度。然后這就是一個(gè)步驟。對于3D并行來(lái)說(shuō),數據并行實(shí)際上是零。所以,您正在將優(yōu)化器狀態(tài)分片到所有不同的GPU上。
而在流水線(xiàn)并行中,假設您的模型有四個(gè)層次,有四個(gè)GPU。您將一層放在每個(gè)GPU上,然后GPU一執行前向傳遞,然后將其激活的輸出發(fā)送到GPU二。它執行前向傳遞,將激活發(fā)送到三,您只是在沿著(zhù)一條線(xiàn)移動(dòng)。那是一個(gè)樸素的方案,所有其他GPU在單個(gè)GPU執行其前向或后向傳遞時(shí)都處于空閑狀態(tài)。所以它被稱(chēng)為流水線(xiàn)并行,因為您將小批次分成了微小批次。
但問(wèn)題在于,您需要一個(gè)非常大的批次大小,以將其分成小批次和微小批次。因此,將這三者結合起來(lái),您將得到一個(gè)3D網(wǎng)格,其中每個(gè)參數、優(yōu)化器狀態(tài)等都映射到每個(gè)GPU上。這就是3D并行。
進(jìn)行此操作時(shí)是否需要所有GPU都相同?還是也可以使用不匹配的GPU?
有兩件事情很重要。如果兩種不同類(lèi)型的GPU之間的VRAM有差異,那么您將受到VRAM較少的GPU的限制,因為它會(huì )耗盡內存。然后您不能使用較大的GPU上剩余的部分。
問(wèn)題在于,我之前提到的同步操作會(huì )讓您受限。因此,在這種情況下,您的移動(dòng)速度將與您最慢或最小的GPU相同。
因此,每個(gè)節點(diǎn)都有一個(gè)不同的網(wǎng)絡(luò )交換機。所以,您最終會(huì )以最慢交換機的速度運行,并且調整一切,使其不比最慢交換機差,這是一個(gè)現實(shí)世界中可能會(huì )遇到的問(wèn)題。
11 異構集群分布的挑戰
Alessio:
就是分片優(yōu)化器和3D并行,將兩者結合在一起,采用這種網(wǎng)格策略。
我會(huì )說(shuō),很多主要的基于GPT的模型都使用了這種方案?,F在很多人更傾向于純粹的ZeRO方案。所以就是純粹的分片。
您只需對所有內容進(jìn)行分片。因為這樣非常容易,每個(gè)人都可以得到相等的切片。不再有流水線(xiàn)階段的問(wèn)題。不再有哪個(gè)張量應該放在哪個(gè)GPU上的問(wèn)題。
我認為,3D并行給您最多的控制權,也是犯錯的最多方式。具體是選擇哪種取決于您是擁有更多工程師還是更多GPU。
Swyx:
這也不算太難,對吧?
您基本上已經(jīng)概述了需要記住的五六個(gè)不同的數字。如果需要達到這種控制水平,您已經(jīng)為每個(gè)人提供了主要的控制杠桿。這很好。絕對的。
Quentin:
問(wèn)題在于,比如說(shuō),好吧,GPT-4發(fā)布了?,F在我們有了VLLMs。
Swyx:
Virtual LLMs,就像Metro of Expert的東西嗎?不,是視覺(jué)的。
所以現在我們有了多模態(tài)模型之類(lèi)的東西。我們如何進(jìn)行分布?我們將其分配到流水線(xiàn)階段嗎?我們只是將其分片嗎?將張量分割并進(jìn)行張量并行嗎?
當您具有這種3D并行方案時(shí),要更改模型并添加新功能變得有點(diǎn)困難。我說(shuō)困難,我的意思是將其調整和修改為適應新功能會(huì )變得困難。
Alessio:
我很好奇,您是否仍然認為這些問(wèn)題集中在訓練、推理、數學(xué)優(yōu)化上,還是還有其他領(lǐng)域需要大家關(guān)注?
我認為在我研究的領(lǐng)域里,有兩個(gè)問(wèn)題是我認為人們應該非常關(guān)心的。
因此,如何將某些模型或某些GPU用于推理,而某些GPU用于訓練?就像我之前提到的,你需要重新學(xué)習所有內容,而且它們具有非常獨特的挑戰。
例如,在訓練期間如何分割一個(gè)KV緩存?這些都是尚未得到充分研究的挑戰。
在多模態(tài)方面,你可能有一個(gè)視覺(jué)變換器和一個(gè)文本變換器。如何分割它們?你是否平均分配?將它們放在不同的GPU上,還是只是將一些視覺(jué)、一些文本參數放在一個(gè)GPU上?
然后,第二個(gè)問(wèn)題是通信往往是一個(gè)瓶頸。所以我們談?wù)摿?D并行,但很多情況下,比如張量并行,你不能跨節點(diǎn)使用。你會(huì )在通信中受到限制。
讓人們在通信基礎設施上花費更少的金錢(qián),而更多地用于GPU,這也是人們需要探索的領(lǐng)域。
關(guān)鍵詞: