LLM學習筆記

ZacksTang發表於2024-06-18

1. 評估榜單

1.1. C-Eval

C-Eval 是一個全面的中文基礎模型評估套件。它包含了13948個多項選擇題,涵蓋了52個不同的學科和四個難度級別。

https://cevalbenchmark.com/static/leaderboard_zh.html?ref=nav.6aiq.com

全部都是各個學科的選擇題,例如:

企業聯合是指企業之間為增強市場競爭力、獲取更大經濟效益而實行的合營或合併。大企業之間的聯合通常叫強強聯合。下列甲乙兩公司的行為屬於企業強強聯合的是____

①甲公司利用乙公司的生產技術力量,投資新專案

②甲公司透過資本市場收購乙公司20%股份

③乙公司把自有資產抵押給銀行,用貸款來購買甲公司的裝置

④乙公司產品透過甲公司的銷售網路迅速進入國際市場

1.2. MMLU

Multi-task Language Understanding on MMLU

https://paperswithcode.com/sota/multi-task-language-understanding-on-mmlu

衡量文字模型的多工準確性。測試涵蓋了57個任務,包括基本數學、美國曆史、電腦科學、法律等多個領域。

旨在透過僅在zero-shot和few-shot設定下評估模型來衡量預訓練期間獲得的知識。

同樣,資料集也是選擇題:

LLM學習筆記

1.3. GSM8K

GSM8k 資料集包含大約 7500 個訓練資料和 1319 個測試資料,主要是小學水平的數學問題,每個資料集都包含基本算術運算(加、減、乘、除),一般需要 2 到 8 步來解決。該資料集可用於多步數學推理。

這個資料集示例如下,可以看到答案裡是包含資料邏輯解答步驟:

LLM學習筆記

1.4. BBH

BIG-Bench Hard(BBH)是BIG-Bench的一個子集,它是一個用於語言模型的多樣化評估套件。BBH專注於BIG-Bench的23個具有挑戰性的任務,這些任務被認為超出了當前語言模型的能力範圍。這些任務是在之前的語言模型評估中沒有超越平均人工評分者的任務。

BBH任務要求multi-step reasoing,並且發現只使用BIG-Bench評估中的few shot,而不使用Chian-of-Thought(CoT)會大大低估語言模型的最佳效能和能力。當在BBH任務中應用CoT提示時,PaLM在23個任務中有10個超過了平均人工評分者的表現,而Codex在23個任務中有17個超過了平均人工評分者的表現。

本質上也是選擇題,但是需要多步reasoning的能力:

LLM學習筆記

2. Context Length

LLM在生成text時,長context length可以記住的大token數量。

在訓練過程中,模型會將文字資料分割成塊或固定長度的視窗進行處理。模型需要在長文字上進行訓練,才能真正充分利用長上下文。訓練序列必須包含包含數千個標記的文件、書籍、文章等長文字。

2.1. 為什麼不用長context length

訓練資料的長度限制了可用上下文長度。那為什麼不在更長的sequence上進行訓練?=》太慢

增加context length會增加模型需要準確預測的可能token組合的數量。這使得模型能夠更可靠地進行long-range的建模,但也需要更多的記憶體和處理能力,從而導致更高的訓練成本。

如果沒有任何最佳化,計算量與上下文長度呈二次比例關係,這意味著一個4096 token的模型需要比一個512 token的模型多64倍的計算量。

可以使用sparse或approximate attention的方法來減少計算量,但是這樣也會影響模型的準確率。

Transformer中使用的標準注意力機制會為所有可能的輸入token pair計算注意力權重,其複雜度為O(n²)。這意味著計算和記憶體需求會隨著輸入序列長度的增加而呈二次增長,限制了Transformer的可擴充套件性和效率。

在生成文字時,模型首先需要計算注意力矩陣。使用100K個上下文和注意力,模型開始生成文字前可能需要幾分鐘的時間。

2.2. 如何提升Attention效率

主流有2個大方向:

  1. Approximating attention:
    1. 降低計算成本,但是也降低了複雜任務上的accuracy
    2. 例如Sparse attention
  2. Exact attention using hardware-aware optimization

最近的主流工作關注在:依賴GPU架構來最佳化attention計算。

Sparse attention

Sparse attention approximates attention by only computing the attention weights for a subset of the input tokens instead of all possible pairs, thus saving time and memory.

There are different ways to implement sparse attention, such as using fixed or static patterns (e.g., local, strided, or block attention) or dynamic or adaptive patterns that depend on the input sequence (e.g., entmax or dynamic sparse attention).

Sparse attention can improve the efficiency and scalability of Transformers, especially for long sequences, but it may also sacrifice some representation power and accuracy. Quadratic attention can achieve high performance and quality, but it may also be computationally expensive and impractical for large-scale applications. Therefore, there is a trade-off between sparsity and complexity in attention mechanisms.

Flash attention

基本原理是避免建立大型的N x N的attention矩陣,因為這個需要對序列長度為N的token上做二次方讀/寫。

FlashAttention應用了兩種技術——切片和重計算。

  1. 切片將輸入分成塊,載入到fast GPU on-chip SRAM.。逐塊計算注意力,以避免建立整個矩陣。
  2. 重計算僅儲存足夠的資訊,在反向傳播期間,在chip上重建注意力矩陣,避免儲存大型中間結果。

作者分析了IO複雜度,證明FlashAttention需要O(N²/M)的記憶體訪問,而標準注意力則需要O(N²),其中M是SRAM的大小。即使增加了重計算的FLOPs(每秒浮點運算次數)的情況下,這種IO-awareness仍使得FlashAttention能夠更快地執行。

實驗證實了加速效果——FlashAttention訓練BERT比MLPerf記錄快15%,GPT-2快3倍,Long Range Arena快2.4倍。

這個想法在FlashAttention-2中得到了進一步的發展。改進的重點是增強序列塊之間的並行性,並最佳化在GPU上的執行緒塊和warp之間的工作劃分。關鍵技術包括減少非矩陣乘操作,將注意力計算線上程之間進行劃分以增加佔用率,並在warp之間分配工作以減少共享記憶體的通訊。實證驗證顯示,FlashAttention-2在A100 GPU上實現了約2倍的加速,達到了理論峰值FLOPs的73%。當用於端到端地訓練GPT模型時,訓練吞吐量達到每個A100的225 TFLOPs/s,比FlashAttention訓練速度快1.3倍。

The improvements promise to enable training models on much longer sequences than before at a similar cost.

Accelerating attention speeds up inference and training, but fitting text into the model while maintaining high output quality remains an issue.

An efficient training and inference is not enough to have an high-quality model.

3. Multi Query Attention

MQA是對Multi Head Attention的一種最佳化實現。兩者區別在於:

  1. MHA裡,每個head都有一組不同的Q、K、V引數矩陣
  2. MQA裡,每個head都共享相同的K、V矩陣,但是Q獨有

推理速度上,生成1個token時,MHA和MQA的encoder分別耗時1.7us和1.5us,而decoder分別是46us和3.8us。說明decoder上MQA比MHA快很多。

在效果上,MQA的PPL有所上升(越小越好),BLEU有所下降(越大越好),換句話說就是效果有所下降。

在實際測試中,模擬chatGLM2的設定,hidden_size = 4096、num_heads =32,num_layers=24輸入一個維度為(5,128,4096)的向量進行文字解碼,生成100個token,耗時對比為:

生成100個token時,MQA解碼平均耗時2.7826秒,MHA解碼平均耗時6.4796秒,簡單來看MQA在decoder解碼加速了一倍。從模型結構來看原始的MHA一層5034W引數,而MQA只有1783W引數,還是透過壓縮引數量來實現視訊記憶體佔用的減少以及推理時間的減少。

視訊記憶體佔用和推理耗時減小是顯而易見的,因為引數量減少了。至於效果變化得很小,只能說多頭attention機制中的多頭其實並不是一定,之前的bert模型有人探索了改變head頭數目,也會保持效果變化不大。在大模型這,可能只需要有不同的head採用不同的query向量,k和v一樣來保證每個頭提取到不同的特徵就夠了。

什麼時候使用MQA有效呢?

1、採用attention的模型,模型規模越大,那麼收益就約明顯。

2、decoder生成任務相比較encoder任務收益明顯大很大,其實decoder生成任務的收益來源於每一次softmax(QK)V注意力計算微小耗時差異的累積,一次生成任務要生成許多個token,一個token需要經歷模型結構層數次的softmax(QK)V注意力的計算。

https://blog.csdn.net/HUSTHY/article/details/131631510

4. 量化

本質上是把例如float point16/32 轉換為int8或int4的精度,降低載入模型的視訊記憶體,降低部署LLM的門檻。

模型量化即以較低的推理精度損失將連續取值的浮點型模型權重進行裁剪和取捨,它是以更少位數的資料型別用於近似表示32位有限範圍浮點型資料的過程,而模型的輸入輸出依然是浮點型,從而達到減少模型尺寸大小、減少模型記憶體消耗及加快模型推理速度等目標。

從效果來看,ChatGLM2-6B不量化的時候載入模型引數視訊記憶體佔用12.8G左右,生成每個token耗時17ms;採用其int8量化佔用視訊記憶體7.3G,生成每個token耗時37ms。也就是說chatGLM的量化並沒有加速推理的能力,只有降低視訊記憶體的能力。

現在 nlp 模型,動不動就 7b、13b 的,有的甚至更大,如果直接使用 bfloat16 載入推理、訓練,需要太大的視訊記憶體了。

於是現在大家都在用 int4、int8 對這種 100b 以上的模型、對 60b 以上的模型做量化。量化之後的模型,雖然效果會變差,但是好像效果還不錯。

有的人,甚至結合 lora,做了 qlora。比如這個專案https://github.com/artidoro/qlora,現在很火。

現在,在最新的 transformers 包裡面,已經整合了相關的方法,你可以使用 int4、int8 對任何 transformers 家族的模型做量化。而且就傳遞幾個引數即可。很簡單。

現在的 int4、int8 方法實現,包括 transformers 整合的量化方法,基本上都是基於 bitsandbytes 包的。

4.1. 量化載入ChatGLM3

預設情況下,ChatGLM3 6B以FP16精度載入,執行起來大概需要13GB視訊記憶體。

6000000000 * 2 / 1024 /1024 / 1024 ~= 11.175GB

GPU顯示記憶體佔用:

| 0 N/A N/A 7892 C .../envs/text2sql/bin/python 12108MiB |

8 INT量化:

model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).quantize(8).cuda()

量化後的GPU佔用為7GB:

| 0 N/A N/A 12413 C .../envs/text2sql/bin/python 7014MiB |

4.2. BitandByte, GPTQ與AWQ

GPTQ和AWQ是目前最優的LLM量化方法之一。GPTQ是Google AI提出的一種基於group量化和OBQ方法的量化方法。AWQ是Facebook AI提出的一種基於activation-aware方法的量化方法。

  • Bitandbyte是常規的quantize方法,bitandbyte量化完,清一色速度慢很多
  • gptq則要case by case。有時候會提速,有時候會變慢
  • autogptq用起來比gptq簡單

5. Fine Tune

在大語言模型中,LoRA,P-Tuning的效果並不好。LoRA在文生圖的效果上還不錯。

LLM模型fine-tune上,也有客戶報LoRA收斂比full tuing收斂要慢。例如full tuing在1個iteration就可以有明顯梯度下降,但是LoRA需要幾個iteration才能達到同樣的效果。

一般fine tune大語言模型還是建議full tuning。ChatGLM 6B建議文字量在1-2w條左右對稱樣本。13B建議在3-4萬左右。

5.1. LLAMA Fine Tune

準備的資料結果(舉例):

LLM學習筆記

train_dataset[0]

{'input_ids': tensor([ 0, 5196, 29906, ..., 32002, 32002, 32002]),

'attention_mask': tensor([1, 1, 1, ..., 0, 0, 0]),

'labels': tensor([ 0, 5196, 29906, ..., 32002, 32002, 32002])}

由於Llama這種自迴歸結構,所以input_ids 和 labels是一樣的。都是透過對應模型的tokenizer,把單詞轉為對應token id。Attention mask是表示有效的token是哪些,後續補全的pad token的mask就全為0。

5.2. deepspeed訓練後的模型大小

做baichuan2-13b的全引數微調,base model本身是24.8GB的,微調後的模型是74.1GB,訓練是用的deepspeed,設定了引數bf16=True,訓練好的檔案config也可以看到torch_dtype為bfloat16,什麼原因微調後的模型變得這麼大?

用deepspeed訓練的話,每個checkpoint folder下會儲存一份ds版的ckpt和hf的ckpt,ds版的會在global step這個folder下,因為額外儲存了當前的optimizer state,所以會大很多。load的時候直接load到checkpoint-xxx路徑下應該就是正常模型的大小

5.3. QLoRA Fine Tune

https://baijiahao.baidu.com/s?id=1767094857485891526&wfr=spider&for=pc

對於650億引數規模的LLaMA模型來說,利用LoRA模型微調依然是成本很高。為此,華盛頓大學的NLP小組提出了QLoRA方法,即LoRA的量化版本。可以支援在單張消費級顯示卡上微調330億引數的大模型,在單張專業級顯示卡上微調650億引數規模大模型。

具體來說,QLoRA方法的實現主要用來3個方面的最佳化:

  1. 4位NormalFloat:這是一種理論上最優的量化資料型別,用於處理正態分佈的資料,其表現優於4位整數和4位浮點數
  2. Double Quantization:這種方法可以透過對量化常數進行量化來減少平均記憶體佔用,平均每個引數可以節省約0.37個bits(對於一個650億引數的模型來說大約節省3GB)。

Paged Optimizers:使用NVIDIA統一記憶體來避免在處理小批次的長序列時出現的梯度檢查點記憶體峰值。

論文中也給出了QLoRA方法與全量微調和LoRA方法差異的示意圖,簡單明瞭:

LLM學習筆記

簡單來說,相比較原始的LoRA,QLoRA將16-bit的transformer模型變成了4-bit的transformer模型(不過這裡說的是4bit的NormalFloat,不是傳統的4-bit),此外利用的NVIDIA的視訊記憶體頁最佳化器進行了最佳化,避免微調過程中出現視訊記憶體的spikes。

其實,對於LoRA方法本身來說,它的記憶體佔用非常小。因此,可以考慮使用多個Adapter來提高效能。換句話說,大模型微調的過程中,對視訊記憶體的消耗主要是啟用梯度,而不是其它的部分,其中,LoRA的Adapter引數規模只有模型權重的千分之二左右。那麼,即使我們增加Adapter其實也不會提高視訊記憶體的消耗。因此,將模型權重進行高強度的量化降低視訊記憶體,再使用多個Adapter來減少模型量化帶來的效能損失,就可以達到降低視訊記憶體要求的同時保留原始模型的效能這2個目標的均衡了。

目前生產上,QLoRA基本上不用。

6. 分散式訓練基本概念

https://mp.weixin.qq.com/s?__biz=MzAxMzA2MDYxMw==&mid=2651608167&idx=2&sn=01cc4707a1d9c8030b140c8705af05c3&chksm=8050ab0db727221b0c88a6f234a4cb46359839821d88581fc3b1820fe1fe8ebc94058c43d41a&scene=27

6.1. 資料並行

把模型引數複製到多個GPU,在不同的GPU上執行1個batch的不同子集。單純的資料並行仍需要模型符合單個GPU的記憶體要求。如果用多個GPU,那代價就是儲存多份重複的引數副本。有些策略可以增加GPU可用的有效RAM,例如在兩次使用之間將引數暫時解除安裝到CPU記憶體。

LLM學習筆記

6.2. Pipeline並行

將模型的順序塊分割到不同的GPU上,每個GPU只持有部分引數。因此同一個模型在每個GPU上消耗的記憶體比例較小。

將一個大模型分割成連續層的大塊是很直接的一種方式。但是,各層的輸入和輸出之間存在著順序上的依賴性,所以一個樸素的實現可能會導致大量的空閒時間,而worker在等待前一個機器的輸出被用作其輸入。

這些等待的時間稱為氣泡(bubbles),浪費了空閒機器可以完成的計算。

LLM學習筆記

目前有更最佳化的方式實現,核心思想是把1個batch分為多個microbatches。每個微批的處理速度應該是成比例的,每個worker在下一個微批可用時就開始工作,從而加速管道的執行。

有了足夠的微批,worker在大部分時間內都處於工作狀態,並且在每個step的開始和結束時氣泡最小。梯度是所有微批的平均值,只有所有微批完成之後才會進行引數更新。

模型被分割的worker的數量通常被稱為pipeline深度。

6.3. Tensor並行

Pipeline並行是把一個模型按“垂直”的層進行分割,而Tensor並行是在一個層內“橫向”分割某些操作。

對於現代模型(例如Transformer)來說,計算瓶頸主要來自啟用batch矩陣與大權重矩陣相乘。矩陣乘法可以認為是成對的行和列之間的點積,所以是有可能在不同的GPU上獨立計算點積,或者在不同的GPU上計算每個點積的一部分,最後再將結果相加。無論採用哪種策略,我們都可以將權重矩陣切分成偶數大小的“碎片”,將每個“碎片”放在不同的GPU上,並使用該“碎片”來計算整個矩陣乘積的相關部分。然後再進行GPU間通訊來合併結果。

LLM學習筆記

大型語言模型中的張量並行機制旨在透過在模型的不同部分上並行處理張量計算來提高訓練和推理的效率。這種方法主要應用於深度學習模型,尤其是包含數十億或數百億引數的大型模型,如GPT-3。以下是大語言模型中張量並行機制的一般步驟:

  • 模型分割: 將整個模型分割成多個子模型,每個子模型負責處理模型的一個子集。這通常透過沿模型的層或其它結構進行劃分來完成。
  • 張量切割: 將每個子模型的輸入張量和引數張量切分成多個子張量。這樣,每個子模型都只負責處理一部分資料。
  • 分配到不同裝置: 將每個子模型分配到不同的處理單元,如GPU或TPU。每個處理單元負責執行相應子模型的計算。
  • 前向傳播: 在前向傳播過程中,每個處理單元獨立計算其負責的子模型的部分。這意味著輸入資料透過分佈在不同裝置上的子模型進行流動,透過並行化的方式加速整個前向傳播過程。
  • 反向傳播: 在反向傳播過程中,梯度資訊沿著相反的路徑傳播回每個處理單元。每個處理單元更新其負責的子模型的引數。
  • 同步和通訊: 由於每個處理單元都在獨立地計算和更新,需要在訓練過程中進行同步和通訊,以確保模型的全域性一致性。這通常涉及到梯度聚合和引數同步的操作。
  • 重複迭代: 重複進行多個訓練迭代,每次迭代都透過張量並行機制加速計算。

透過張量並行機制,可以更有效地利用多個處理單元,減少訓練和推理時間。這種方法的有效性取決於模型的結構、硬體的效能,以及如何劃分模型和張量。

6.4. 混合專家系統(MoE)

對於任何輸入,MoE策略都只有一部分網路用來計算輸出。

比如說一個網路里有很多權重,網路可以在推理時透過門控機制選擇具體使用哪套。這樣就可以在不增加計算成本的情況下增加引數量。

每個權重被稱為一個“專家”,訓練目標是希望網路能夠學會將專門的計算和技能分配給每個“專家”。不同的專家可以託管在不同的GPU上,為擴大模型使用的GPU數量提供了一個明確的方法。

LLM學習筆記

GShard可以將MoE Transformer的規模擴充套件到6000億個引數,其方案是隻有MoE層被分割到多個TPU裝置上,而其他層是完全重複的。

Switch Transformer則是透過將一個輸入路由(routing)到一個專家,成功將模型規模擴充套件到數萬億的引數,甚至稀疏度更高。

https://zhuanlan.zhihu.com/p/672002822

MoEs 雖然能夠高效地進行預訓練並且在推理速度上超越密集型模型,但同時它們也面臨一些挑戰:

  • 在訓練階段:MoEs 提供了極高的計算效率預訓練,但在微調過程中卻面臨泛化的困難,這常常導致過擬合的問題。
  • 在推理階段:雖然 MoE 模型擁有眾多引數,但在推理時只有部分引數被使用。這意味著與擁有同等引數數量的密集型模型相比,MoE 的推理速度要快得多。

然而,所有的引數都需要載入到 RAM 中,因此對記憶體的需求相當高。例如,對於一個像 Mixtral 8x7B 的 MoE,我們需要有足夠的 VRAM 來支援一個 47B 引數的密集模型。為何是 47B 而非 8 x 7B = 56B 呢?這是因為在 MoE 模型中,只有 FFN 層被當做獨立的專家,其他部分的模型引數則是共享的。

同時,假設每個令牌只用兩個專家進行推理,那麼推理速度(FLOPs)相當於使用一個 12B 模型(不是 14B 模型),因為它計算的是 2x7B 的矩陣乘法,但某些層是共享的

6.5. Offloading(解除安裝)

降低GPU Memory使用的方式之一。

將未使用的資料暫時offload到cpu或不同的裝置上,然後在需要時將其讀回。樸素的實現方式會大大降低訓練速度,但複雜的實現方式會預先獲取資料,這樣裝置就不需要再等待了。

這個想法的一個具體實現是ZeRO,它將引數、梯度和最佳化器狀態分割到所有可用的硬體上,並根據實際需要再將它們具體化。

7. DeepSpeed

7.1. 原理

為了解決這些記憶體挑戰,DeepSpeed 實施了一種被稱為 ZeRO(Zero Redundancy Optimizer)的三階段策略來管理記憶體:

  1. 最佳化器狀態分割槽(ZeRO 階段 1):這個初始階段涉及將最佳化器狀態進行分片(分割槽),分配給資料並行的工作節點或 GPU。每個 GPU 不再儲存完整的最佳化器狀態集,而是隻儲存其中的一部分,從而降低了整體記憶體需求。
  2. 梯度分割槽(ZeRO 階段 2):在第一個階段的基礎上,ZeRO 階段 2 還將梯度分割槽到資料並行的工作節點或 GPU。這意味著每個 GPU 只儲存梯度的一部分,進一步減小了記憶體佔用。
  3. 引數分割槽(ZeRO 階段 3):這個最終階段更進一步,不僅對最佳化器狀態和梯度進行分割槽,還將模型引數分配給資料並行的工作節點或 GPU。現在,每個 GPU 只儲存模型引數的一部分,使得更大的模型能夠適應單個 GPU 機器內。

除了這些階段之外,DeepSpeed 還引入了兩種解除安裝策略,以降低 GPU 記憶體使用,作為對較慢模型訓練速度的一種折衷:

  1. 最佳化器解除安裝:在 ZeRO 階段 2 的基礎上,這個策略將梯度和最佳化器狀態解除安裝到 CPU 或磁碟。這有效地釋放了 GPU 記憶體用於其他計算,進一步減少了記憶體使用。
  2. 引數解除安裝:這個策略建立在 ZeRO 階段 3 之上,透過將模型引數解除安裝到 CPU 或磁碟。類似於最佳化器解除安裝,這種方法提供了額外的記憶體需求減少,使得即使是更大的模型也能夠在可用資源下進行訓練。

這張表明了在 ZeRO 的三個階段中,透過不同的資料並行度(DP)對多個模型記憶體佔用的減少:

LLM學習筆記

簡單來說,假設我們正在研究各種大小的模型,從具有75億引數的較小模型到具有1萬億引數的龐大模型。我們可以測量這些模型使用的記憶體量,以 GB 為單位。

我們有不同的分割槽策略階段,如“os”(代表最佳化器狀態)、“os+g”(最佳化器狀態加梯度)和“os+g+p”(最佳化器狀態加梯度加引數)。當我們將這些策略與資料並行(DP)結合使用時,我們發現記憶體使用顯著減少。

換句話說,這些策略有助於大幅減少模型所需的記憶體量,使得更容易處理較大的模型。

透過這些創新的記憶體管理策略,DeepSpeed有效地應對記憶體消耗的挑戰,實現了對更大更復雜模型的訓練。

7.2. 引數解釋

https://deepspeed.readthedocs.io/en/latest/zero3.html

  1. zero_stage : 這個對應者DeepSpeed工具中的zero方式,分別是:
    1. 0:disable
    2. 1:optimizer state partitioning
    3. 2:optimizer + gradient state partitioning
    4. 3:optimizer + gradient + parameter partitioning
  2. offload : ZeRO-Offload 透過利用主機CPU上的計算和記憶體資源來執行最佳化器,從而減少此類模型的GPU計算和記憶體需求。
  3. local_rank : 分散式訓練時的一個變數,用於標識當前 GPU 裝置的本地排名(本機排名,與global-rank不同)
    1. -1:禁止分散式設定,一般單機多卡不需要分散式
    2. 0:程序透過local_rank來標識自己,local_rank為0的表示為master
  4. gradient_checkpointing : 降低深度學習模型訓練過程中記憶體消耗的技術

在 DeepSpeed 中,local_rank 引數是用於指定當前程序在本地(節點內)的排名(rank)的引數。在分散式訓練中,多個程序可能同時在一個節點上執行,每個程序都有一個唯一的本地排名。

具體來說,local_rank 引數用於標識當前程序在節點內的位置。這對於分散式訓練非常重要,因為它幫助確定每個程序在整個分散式系統中的唯一標識。透過設定不同的 local_rank,可以確保每個程序都知道自己在整個訓練中的位置,從而更有效地協同工作。

8. 推理

server side batch是推理服務的標配(以提升server側吞吐量為目的).

LLM學習筆記

8.1. 推理框架-TGI

https://www.zhihu.com/question/625415776?utm_id=0

HuggingFace推出。

8.2. 推理框架FasterTransformer

英偉達推出,後續推出了TensorRT-LLM後,就不再維護FasterTransformer了。

8.3. 選擇推理框架的維度

並非有1個推理框架(例如vLLM,TensorRT-LLM,TGI,DJL等等)適合所有模型,同一個模型在不同的推理框架上可能表現不一樣。

部分參考資料:

  • vllm,g5 ,LLama2-7b 跑下來 290 token/s
  • vllm的最大優勢就是吞吐很好,且在batch 變大的情況下,latency的增加比較小

9. Chain of Thought

基本形態:one-shot prompt,給出一個step by step解決問題的例子:

LLM學習筆記

其他形態:

  1. Zero-Shot-CoT:prompt末尾加”Let’s think step by step”。使用非常簡單,但是效果不一定有few-shot好
  2. Manual-CoT:使用few-shot,在輸入問題之前,手動設計一些問題和答案的樣例(樣例的答案給出中間推理步驟),這些問題和答案都需要手動構造,所以叫 Manual-CoT。很明顯,要想模型效果好,需要投入一定人力成本
  3. Auto-CoT:Auto-CoT 其實也是受到了 Manual-CoT 的啟發,既然 Manual-CoT 比 Zero-Shot-CoT 的效能要好,而且效能好的關鍵就在於人工設計的問題、中間推理步驟和答案的樣例,那麼就可以考慮將這部分進行自動化,從而節省人工成本

下面是一個Auto-CoT的例子:

LLM學習筆記

Auto-CoT 包括兩個主要階段:(i)問題聚類:將給定資料集中的問題劃分為幾個聚類;(ii)演示抽樣:從每個聚類中選擇一個代表性問題,並使用簡單的啟發式方法使用 Zero-Shot-CoT 生成其推理鏈。總體過程如上圖所示。

透過多樣性選取有代表性的問題,對於每一個取樣的問題拼接上“Let’s think step by step”(類似於 Zero-Shot-CoT )輸入到語言模型,讓語言模型生成中間推理步驟和答案,然後把這些所有采樣的問題以及語言模型生成的中間推理步驟和答案全部拼接在一起,構成少樣本學習的樣例,最後再拼接上需要求解的問題一起輸入到語言模型中進行續寫。最終模型續寫出了中間的推理步驟以及答案,並且質量非常高。

值得一提的是,在十個資料集上 Auto-CoT 是可以匹配甚至超越 Manual-CoT 的效能,也就說明自動構造的 CoT 的問題、中間推理步驟和答案樣例比人工設計的還要好,而且還節省了人工成本。在 Auto-CoT 中,其實也是用到了很多個“Let’s think step by step”對每個取樣的問題分別觸發中間推理步驟和答案,這也是為什麼叫它 “Let's think not just step by step but also one by one”。

10. Agent

10.1. Assistants API

OpenAI的Assistants API的常規工作流為:

  1. 建立1個Assistant,並指定其instructions和model。如果需要,也可以啟用如Code Interpreter、Retrieval和Function calling的tools
  2. 在每個新使用者開啟對話時,建立一個Thread
  3. 在使用者提問時,加入Messages到Thread
  4. 在Thread裡執行Assistant來觸發回覆。這一步會自動呼叫相關的tools

https://cookbook.openai.com/examples/assistants_api_overview_python

本質上就是個Agent。OpenAI提供了直接整合Code Interpreter、自定義Function以及Retrieval的tools。

可以讓Assistant決定呼叫提供的工具,例如Code Interpreter生成程式碼解決問題,或是提供自定義的Function來解決問題。

10.2. Function Calling

提供function的描述,讓模型智慧地輸出一個包含了呼叫1個或多個function資訊的JSON物件。本質上gpt不會自動呼叫function,而是返回撥用function的JSON資訊。

https://cookbook.openai.com/examples/how_to_call_functions_with_chat_models

例如:

LLM學習筆記

前面定義了function的描述,名稱,功能等,然後基於使用者的資訊,返回撥用的function名稱以及傳入的引數(以json的格式)。

11. vLLM

開源的大模型推理加速框架,透過Paged Attention高效地管理attention中快取的張量,實現比HuggingFace Transformers高14-24倍的吞吐量。

11.1. LLM的效能受到記憶體限制

在自迴歸解碼過程中,LLM的所有輸入token都會生成attention機制的key和value的張量,並且這些張量被保留在GPU記憶體中,用來生成下一個token。

這些快取的key和value的張量通常稱為KV快取。KV快取有2個特點:

  1. 記憶體佔用大:在LLaMA-13B中,單個序列的KV快取佔用高達1.7GB的記憶體
  2. 動態化:其大小取決於序列的長度,而序列長度高度易變,且不可預測

因此,有效管理KV快取是一個重大挑戰。對此,研究團隊發現現有系統由於碎片化和過度保留而浪費了60%至80%的記憶體。

用團隊的導師Joey Gonzalez的一句話來講:GPU記憶體碎片化=慢。

11.2. PagedAttention機制

為了解決這個問題,引入了PagedAttention機制,它允許在非連續的記憶體空間中儲存連續的key和value。

具體來說,PagedAttention將每個序列的KV快取分為若干個block,每個block包含固定數量token的key和value張量。在注意力計算過程中,PagedAttention核心能夠高效地識別和提取這些block。

由於這些塊在記憶體中不需要連續,因此也就可以像作業系統的虛擬記憶體一樣,以更靈活的方式管理key和value張量——將塊看作page,token看作bytes,序列看作process。

序列的連續邏輯塊透過塊表對映到非連續的物理塊。隨著生成新的token,物理塊會按需進行分配。LLM學習筆記

PagedAttention將記憶體浪費控制在了序列的最後一個塊中。

在實踐中,這帶來了接近最優的記憶體使用——僅有不到4%的浪費。

而這種記憶體效率的提升,能讓系統將更多的序列進行批處理,提高GPU利用率,從而顯著提高吞吐量。

此外,PagedAttention還具有另一個關鍵優勢:高效的記憶體共享。

比如在並行取樣中,就能從相同的提示生成多個輸出序列。在這種情況下,提示的計算和記憶體可以在輸出序列之間共享。

11.3. Paged Attention高效地記憶體共享

比如在並行取樣中,就能從相同的prompt生成多個輸出序列。在這種情況下,prompt的計算和記憶體可以在輸出序列之間共享。

LLM學習筆記

PagedAttention透過塊表自然地實現了記憶體共享。

類似於程序共享物理頁的方式,PagedAttention中的不同序列可以透過將它們的邏輯塊對映到相同的物理塊來共享塊。

為了確保安全,PagedAttention會跟蹤物理塊的引用計數,並實現了寫時複製機制。

LLM學習筆記

PagedAttention的記憶體共享極大減少了複雜取樣演算法(如並行取樣和束搜尋)的記憶體開銷,將它們的記憶體使用量減少了高達55%。這可以將吞吐量提高多達2.2倍。

https://baijiahao.baidu.com/s?id=1769290162439240324&wfr=spider&for=pc

11.4. 部署ChatGLM2模型

在不使用vLLM時,問ChatGLM2-6b一個問題“晚上睡不著應該怎麼辦”,推理耗時13-14s。輸出379箇中文字元,token生成速度約為30 token/s 左右。

使用vLLM部署後,推理耗時7.6s左右,輸出218箇中文字元,token生成速度約為 28個token/s左右

INFO 02-06 09:01:09 llm_engine.py:649] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 20.6 tokens/s, Running: 1 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.7%, CPU KV cache usage: 0.0%

12. Realtime Stable Diffusion

加速推理,以及實時SD影片:

https://github.com/cumulo-autumn/StreamDiffusion

SD Turbo 1步成圖,結合stream方案一秒100張圖

13. topP與temperature

  • Temperature:控制選擇單詞的隨機性。更低的值可以讓生成的文字更一致、可控;更高的值給予模型更多的創造性,生成的文字一致的可能性更低。
    • 為0表示永遠選擇最可能的單詞作為下一個輸出單詞
  • Top_p:考慮候選單詞的數量。更高的值表示模型會考慮更多的候選單詞,甚至是較為不可能的單詞,讓生成的文字更多樣化.
    • Top_p = 0.5:這意味著僅考慮那些總機率至少達到總機率的50%的單詞,排除了可能性較低的單詞,並保持了一定水平的多樣性響應。例如:如果您要求一本冒險書的標題,Top-p為0.5,模型可能會提出:“藍山的神秘”。
    • Top_p = 0.9:這包括了更多的選擇單詞,允許更多的變化和獨創性。例如:對於同樣的冒險書標題和Top_p為0.9,模型可能會建立:“深淵之聲:勇者的肖像”。