在 Google Kubernetes Engine (GKE) 上使用 GPU 最佳化大型語言模型推論的最佳做法

Google Kubernetes Engine (GKE) 可精細控管大型語言模型 (LLM) 推論,提供最佳效能和成本。本指南說明如何使用 vLLM 和 Text Generation Inference (TGI) 服務架構,在 GKE 上透過 GPU 最佳化開放式 LLM 的推論和服務。

如需所有最佳做法的檢查清單摘要,請參閱「檢查清單摘要」。

如要全面瞭解所有 GKE 最佳做法,請參閱「GKE 最佳做法」。

目標

本指南適用於生成式 AI 客戶、新或現有的 GKE 使用者、機器學習工程師,以及有興趣使用 Kubernetes 搭配 GPU 最佳化 LLM 工作負載的 LLMOps (DevOps) 工程師。

完成本指南後,您將能夠:

  • 選擇經後訓練的 LLM 最佳化技術,包括量化、張量平行處理和記憶體最佳化。
  • 考慮採用這些最佳化技術時,請權衡高階取捨條件。
  • 使用 vLLM 或 TGI 等服務架構,並啟用最佳化設定,將開放原始碼 LLM 模型部署至 GKE。

大型語言模型服務最佳化技術總覽

與非 AI 工作負載不同,LLM 工作負載通常會依賴矩陣乘法運算,因此延遲時間較長,處理量也較低。如要提升 LLM 推論效能,可以使用專門的硬體加速器 (例如 GPU 和 TPU) 和最佳化的服務架構。

您可以採用下列一或多項最佳做法,縮短 LLM 工作負載延遲時間,同時提高處理量和成本效益:

本指南中的範例會使用 Gemma 7B LLM,搭配 vLLM 或 TGI 服務架構來套用這些最佳做法;不過,文中說明的概念和功能適用於大多數熱門的開放式 LLM。

事前準備

嘗試本指南中的範例之前,請先完成下列必要工作:

  1. 請按照下列指南中的操作說明,存取 Gemma 模型、準備環境,以及建立及設定 Google Cloud 資源:

    請務必將 Hugging Face 存取權杖儲存至 Kubernetes Secret。

  2. 將 https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/ 範例存放區複製到本機開發環境。

  3. 將目前使用的目錄變更為 /kubernetes-engine-samples/ai-ml/llm-serving-gemma/。

最佳做法:量化

量化技術類似於有損圖片壓縮,可透過以較低精確度格式 (8 位元或 4 位元) 表示權重,縮減模型大小,進而降低記憶體需求。不過,與圖片壓縮一樣,量化也涉及取捨:模型大小縮減可能會導致準確度降低。

量化方法有很多種,各有優缺點。部分模型 (例如 AWQ 和 GPTQ) 需要預先量化,並可在 Hugging Face 或 Kaggle 等平台使用。舉例來說,如果您在 Llama-2 13B 模型上套用 GPTQ,並在 Gemma 7B 模型上套用 AWQ,就能在單一 L4 GPU 上提供模型,而不必像未量化時一樣使用兩個 L4 GPU。

您也可以使用 AutoAWQ 和 AutoGPTQ 等工具執行量化作業。這些方法可改善延遲和輸送量。相較之下,使用 EETQ 和 bitsandbytes 程式庫進行量化的技術不需要預先量化模型,因此在沒有預先量化版本時,是合適的選擇。

要使用哪種量化技術,取決於您的具體目標,以及該技術與您想使用的服務架構是否相容。詳情請參閱 Hugging Face 的量化指南。

選取其中一個分頁,即可查看使用 TGI 或 vLLM 架構套用量化的範例:

TGI

GKE 支援下列 TGI 量化選項:

  • awq
  • gptq
  • eetq
  • bitsandbytes
  • bitsandbytes-nf4
  • bitsandbytes-fp4

AWQ 和 GPTQ 量化方法需要預先量化的模型,而 EETQ 和 bitsandbytes 量化則可套用至任何模型。如要進一步瞭解這些選項,請參閱這篇 Hugging Face 文章。

如要使用量化功能,請在啟動模型伺服器時設定 -–quantize 參數。

下列程式碼片段說明如何在 GKE 上使用 TGI,透過 bitsandbytes 量化功能最佳化 Gemma 7B。

args:
- --model-id=$(MODEL_ID)
- --num-shard=2
- --quantize=bitsandbytes

如要套用這項設定,請使用下列指令:

kubectl apply -f tgi/tgi-7b-bitsandbytes.yaml

vLLM

GKE 支援下列 vLLM 量化選項:

如要搭配 vLLM 使用模型量化功能,模型必須預先量化。啟動執行階段時,請設定 –quantization 參數。

下列程式碼片段說明如何使用 GKE 上的 vLLM,透過 awq 量化功能最佳化 Gemma 7B 模型:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --quantization=awq
env:
- name: MODEL_ID
  value: google/gemma-7b-AWQ
resources:
  requests:
    nvidia.com/gpu: 1
  limits:
    nvidia.com/gpu: 1

如要套用這項設定,請使用下列指令:

kubectl apply -f vllm/vllm-7b-awq.yaml

使用 KV 快取量化功能縮短延遲時間

您可以運用 FP8 E5M2 KV 快取量化功能,大幅減少 KV 快取記憶體用量並縮短延遲時間,特別是針對大型批次大小。 但這會降低推論準確度。

如要啟用 FP8 E5M2 KV 快取量化功能,請設定 --kv-cache-dtype fp8_e5m2 參數:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --kv-cache-dtype=fp8_e5m2
- --max-model-len=1200
resources:
  requests:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1
  limits:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1

如要套用這項設定,請使用下列指令:

kubectl apply -f vllm/vllm-7b-kvcache.yaml

最佳做法:張量平行處理

張量平行處理是一種技術,可將運算負載分配到多個 GPU,這對於執行超過單一 GPU 記憶體容量的大型模型至關重要。這個方法可讓您使用多個經濟實惠的 GPU,不必使用昂貴的單一 GPU,因此更具成本效益。還能提升模型推論輸送量。張量平行處理會利用張量運算可獨立對較小資料區塊執行的特性。

如要進一步瞭解這項技術,請參閱 Hugging Face 的張量平行處理指南。

選取下列任一分頁標籤,即可查看使用 TGI 或 vLLM 架構套用張量平行處理的範例:

TGI

使用 TGI 時,服務執行階段預設會使用 Pod 可用的所有 GPU。您可以指定 --num-shard 參數,並將值設為 GPU 數量,藉此設定要使用的 GPU 數量。

如要查看支援張量平行處理的模型清單,請參閱 Hugging Face 說明文件的模型清單。

下列程式碼片段說明如何使用張量平行處理和兩個 L4 GPU,最佳化 Gemma 7B 指令調整模型:

args:
- --model-id=$(MODEL_ID)
- --num-shard=2

如要套用這項設定,請使用下列指令:

kubectl apply -f tgi/tgi-7b-it-tensorparallelism.yaml

在 GKE Autopilot 叢集中,執行這項指令會建立 Pod,最低資源需求為 21 個 vCPU 和 78 GiB 記憶體。

vLLM

vLLM 支援分散式張量平行推論。如果有多個可用的 GPU,vLLM 會預設啟用這項功能。

下列程式碼片段說明如何使用張量平行處理和兩個 L4 GPU,最佳化 Gemma 7B 指令微調模型:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=2

如要套用這項設定,請使用下列指令:

kubectl apply -f vllm/vllm-7b-it-tensorparallelism.yaml

在 GKE Autopilot 叢集中,執行這項指令會建立 Pod,最低資源需求為 21 個 vCPU 和 78 GiB 記憶體。

最佳做法:模型記憶體最佳化

如要提高推論效率,必須最佳化 LLM 的記憶體用量。本節將介紹注意力層最佳化策略,例如分頁注意力機制和快速注意力機制。這些策略可提升記憶體效率,進而延長輸入序列並縮短 GPU 閒置時間。本節也會說明如何調整模型輸入和輸出大小,以符合記憶體限制,並針對特定服務架構進行最佳化。

注意力層最佳化

自注意層 可讓模型在語言處理工作中瞭解語境,因為字詞的意義會因語境而異。 不過,這些層會在 GPU vRAM 中儲存輸入權杖權重、鍵 (K) 和值 (V)。因此,輸入序列越長,大小和運算時間就會以二次方速度成長。

處理長輸入序列時,自注意力機制的負擔可能會很大,因此使用 KV 快取特別實用。這種最佳化方法可將運算處理作業降至線性複雜度。

最佳化 LLM 注意力機制的具體技術包括:

  • 分頁注意力:分頁注意力採用類似 OS 虛擬記憶體的分頁技術,可改善大型模型和長輸入序列的記憶體管理。這項技術可有效減少 KV 快取中的片段和重複內容,讓輸入序列更長,不會耗盡 GPU 記憶體。
  • Flash attention:Flash attention 可減少詞元生成期間 GPU RAM 和 L1 快取之間的資料移轉,進而減少 GPU 記憶體瓶頸。這樣可以消除運算核心的閒置時間,大幅提升 GPU 的推論和訓練效能。

調整模型輸入和輸出大小

記憶體需求取決於輸入和輸出大小。輸出內容越長、脈絡資訊越多,需要的資源就越多;輸出內容越短、脈絡資訊越少,則可使用較小、較便宜的 GPU,節省成本。

選取任一分頁,即可查看在 TGI 或 vLLM 架構中,調整模型輸入和輸出記憶體需求的範例:

TGI

TGI 服務執行階段會在啟動期間檢查記憶體需求,如果模型可能佔用的最大記憶體用量不符合可用的 GPU 記憶體,就不會啟動。這項檢查可避免記憶體密集型工作負載發生記憶體不足 (OOM) 導致當機的問題。

GKE 支援下列 TGI 參數,可最佳化模型記憶體需求:

以下程式碼片段說明如何使用單一 L4 GPU 提供 Gemma 7B 指令微調模型,並設定 --max-total-tokens=3072, --max-batch-prefill-tokens=512, --max-input-length=512 參數:

args:
- --model-id=$(MODEL_ID)
- --num-shard=1
- --max-total-tokens=3072 
- --max-batch-prefill-tokens=512
- --max-input-length=512
env:
- name: MODEL_ID
  value: google/gemma-7b

如要套用這項設定,請使用下列指令:

kubectl apply -f tgi/tgi-7b-token.yaml

vLLM

在 vLLM 中,設定模型的脈絡長度,這會直接影響 KV 快取大小和 GPU RAM 需求。較短的脈絡長度可使用更經濟實惠的 GPU。預設值為模型可接受的權杖數量上限。如有需要,請使用 --max-model-len MAX_MODEL_LEN 限制脈絡長度上限。

舉例來說,Gemma 7B 指令微調模型預設的上下文長度為 8192,超過單一 NVIDIA L4 GPU 的記憶體容量。如要在 L4 上部署,請將 --max-model-len 設為小於 640 的值,限制提示和輸出的總長度。這項調整可讓模型在單一 L4 GPU 上執行,即使預設脈絡長度較長也沒問題。

如要使用修改後的權杖限制進行部署,請使用下列程式碼片段:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --max-model-len=600

如要套用這項設定,請使用下列指令:

kubectl apply -f vllm/vllm-7b-token.yaml

檢查清單摘要

最佳化目標 練習
延遲時間
  • 優先使用強大的 GPU: 考慮升級至運算能力和記憶體 I/O 輸送量更高的 GPU。
  • 探索量化: AWQ 等技術可縮短延遲時間,但請注意可能導致準確度降低。
處理量
  • 水平擴充: 增加服務副本 (Pod) 數量,分散工作負載。
  • 使用張量平行處理:如果大型模型超出單一 GPU 的容量,請使用張量平行處理,將運算作業分散到多個 GPU。如果是較小的模型,建議使用多個張量平行處理為「1」的副本,避免產生額外負擔。
  • 批次要求和量化:合併要求,並探索可維持可接受準確率的量化技術。
具成本效益
  • 選擇較小的模型: 在系列中選取符合資源限制和預算的模型。
  • 套用量化:使用量化技術降低記憶體需求,特別是處理大型模型時。
  • 限制脈絡長度: 限制脈絡長度可進一步減少記憶體用量,並在較小、更具成本效益的 GPU 上執行。

後續步驟