Best Practices für die Optimierung der Inferenz von Large Language Models mit GPUs in der Google Kubernetes Engine (GKE)


Google Kubernetes Engine (GKE) bietet eine detaillierte Kontrolle für die Inferenz von Large Language Models (LLM) bei optimaler Leistung und Kosten. In diesem Leitfaden werden Best Practices für die Optimierung der Inferenz und Bereitstellung offener LLMs mit GPUs in der GKE mit den Bereitstellungs-Frameworks vLLM und Text Generation Inference (TGI) beschrieben.

Eine zusammenfassende Checkliste mit den Best Practices finden Sie in der Zusammenfassung der Checkliste.

Ziele

Dieser Leitfaden richtet sich an Kunden von generativer KI, neue oder bestehende GKE-Nutzer, ML-Entwickler und LLMOps-Entwickler (DevOps), die ihre LLM-Arbeitslasten mithilfe von GPUs mit Kubernetes optimieren möchten.

Am Ende dieses Leitfadens können Sie Folgendes tun:

  • Wählen Sie LLM-Optimierungstechniken nach dem Training aus, einschließlich Quantisierung, Tensorparallelität und Speicheroptimierung.
  • Berücksichtigen Sie die allgemeinen Vor- und Nachteile dieser Optimierungstechniken.
  • Offene LLM-Modelle mithilfe von Bereitstellungs-Frameworks wie vLLM oder TGI mit aktivierten Optimierungseinstellungen in GKE bereitstellen

Übersicht über Techniken zur Optimierung der LLM-Bereitstellung

Im Gegensatz zu Nicht-KI-Arbeitslasten haben LLM-Arbeitslasten aufgrund ihrer Abhängigkeit von Matrixmultiplikationsvorgängen in der Regel eine höhere Latenz und einen geringeren Durchsatz. Zur Verbesserung der LLM-Inferenzleistung können Sie spezielle Hardwarebeschleuniger (z. B. GPUs und TPUs) und optimierte Bereitstellungs-Frameworks verwenden.

Sie können eine oder mehrere der folgenden Best Practices anwenden, um die Latenz der LLM-Arbeitslast zu reduzieren und gleichzeitig den Durchsatz und die Kosteneffizienz zu verbessern:

In den Beispielen in diesem Leitfaden wird das Gemma 7B-LLM in Verbindung mit den vLLM- oder TGI-Bereitstellungs-Frameworks verwendet, um diese Best Practices anzuwenden. Die beschriebenen Konzepte und Features gelten jedoch für die gängigsten offenen LLMs.

Hinweise

Führen Sie die folgenden Aufgaben aus, bevor Sie die Beispiele in dieser Anleitung ausprobieren:

  1. Folgen Sie den Anleitungen in diesen Anleitungen, um Zugriff auf das Gemma-Modell zu erhalten, Ihre Umgebung vorzubereiten sowie Google Cloud-Ressourcen zu erstellen und zu konfigurieren:

    Speichern Sie das Hugging Face-Zugriffstoken in Ihrem Kubernetes-Secret.

  2. Klonen Sie das Beispiel-Repository https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/ in Ihre lokale Entwicklungsumgebung.

  3. Ändern Sie Ihr Arbeitsverzeichnis in /kubernetes-engine-samples/ai-ml/llm-serving-gemma/:

Best Practice: Quantisierung

Die Quantisierung ist eine Technik, die analog zur verlustbehafteten Bildkomprimierung ist, die die Modellgröße durch Darstellung von Gewichtungen in Formaten mit niedrigerer Genauigkeit (8-Bit oder 4-Bit) reduziert, wodurch der Speicherbedarf verringert wird. Wie bei der Bildkomprimierung ist auch bei der Quantisierung ein Kompromiss erforderlich: Eine geringere Modellgröße kann zu einer geringeren Genauigkeit führen.

Es gibt verschiedene Quantisierungsmethoden, die jeweils ihre eigenen Vor- und Nachteile haben. Einige, wie AWQ und GPTQ, erfordern eine Vorquantisierung und sind auf Plattformen wie Hugging Face oder Kaggle verfügbar. Wenn Sie beispielsweise GPTQ auf das Llama-2 13B-Modell und AWQ auf das Gemma 7B-Modell anwenden, können Sie die Modelle auf einer einzelnen L4-GPU statt auf zwei L4-GPUs ohne Quantisierung bereitstellen.

Sie können die Quantisierung auch mit Tools wie AutoAWQ und AutoGPTQ ausführen. Diese Methoden können Latenz und Durchsatz verbessern. Im Gegensatz dazu erfordern Techniken mit EETQ und der Bibliothek bitsandbytes für die Quantisierung keine vorab quantisierten Modelle. Daher können sie eine geeignete Wahl sein, wenn keine vorab quantisierten Versionen verfügbar sind.

Die beste Quantisierungstechnik hängt von Ihren spezifischen Zielen und der Kompatibilität der Technik mit dem gewünschten Bereitstellungs-Framework ab. Weitere Informationen finden Sie im Quantisierungsleitfaden von Hugging Face.

Wählen Sie einen dieser Tabs aus, um ein Beispiel für die Anwendung der Quantisierung mit den TGI- oder vLLM-Frameworks zu sehen:

TGI

GKE unterstützt die folgenden Quantisierungsoptionen mit TGI:

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

Für die Quantisierungsmethoden "AWQ" und "GPTQ" sind vorab quantisierte Modelle erforderlich, während die Quantisierung mit EETQ und bitsandbytes auf jedes Modell angewendet werden kann. Weitere Informationen zu diesen Optionen finden Sie in diesem Artikel zu Hugging Face.

Wenn Sie die Quantisierung verwenden möchten, legen Sie beim Starten des Modellservers den Parameter -–quantize fest.

Im folgenden Snippet wird gezeigt, wie Sie Gemma 7B mit bitsandbytes-Quantisierung mithilfe von TGI in GKE optimieren.

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

vLLM

GKE unterstützt diese Quantisierungsoptionen mit vLLM:

Um die Modellquantisierung mit vLLM zu verwenden, müssen die Modelle vorab quantisiert werden. Legen Sie beim Starten der Laufzeit den Parameter –quantization fest.

Das folgende Snippet zeigt, wie Sie das Gemma 7B-Modell mit der awq-Quantisierung mithilfe von vLLM in GKE optimieren:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

Latenz durch KV-Cache-Quantisierung verbessern

Mit der Quantisierung des KV-Caches mit FP8 E5M2 können Sie den Arbeitsspeicherbedarf des KV-Caches erheblich reduzieren und die Latenz verbessern, insbesondere bei großen Batchgrößen. Dies reduziert jedoch die Inferenzgenauigkeit.

Legen Sie den Parameter --kv-cache-dtype fp8_e5m2 fest, um die FP8 E5M2 KV-Cache-Quantisierung zu aktivieren:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

Best Practice: Tensorparallelität

Tensor-Parallelität ist eine Technik, die die Rechenlast auf mehrere GPUs verteilt. Dies ist wichtig, wenn Sie große Modelle ausführen, die die Arbeitsspeicherkapazität einer einzelnen GPU überschreiten. Dieser Ansatz kann kostengünstiger sein, da Sie mehrere erschwingliche GPUs anstelle einer einzelnen teuren GPU verwenden können. Außerdem kann der Modellinferenzdurchsatz verbessert werden. Die Tensor-Parallelität nutzt die Tatsache, dass Tensorvorgänge unabhängig für kleinere Datenblöcke ausgeführt werden können.

Weitere Informationen zu dieser Technik finden Sie im Leitfaden zu Tensorparallelität von Hugging Face.

Wählen Sie einen dieser Tabs aus, um ein Beispiel für die Anwendung der Tensor-Parallelität mit den TGI- oder vLLM-Frameworks zu sehen:

TGI

Bei TGI verwendet die Bereitstellungslaufzeit standardmäßig alle GPUs, die dem Pod zur Verfügung stehen. Sie können die Anzahl der zu verwendenden GPUs festlegen, indem Sie für den Parameter --num-shard die Anzahl der GPUs als Wert angeben.

In der Hugging Face-Dokumentation finden Sie eine Liste der Modelle, die für den Tensorparallelismus unterstützt werden.

Das folgende Snippet zeigt, wie das für die Anweisung optimierte Gemma 7B-Modell mit Tensor-Parallelität und zwei L4-GPUs optimiert wird:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

In GKE Autopilot-Clustern wird durch Ausführen dieses Befehls ein Pod mit Mindestressourcenanforderungen von 21 vCPUs und 78 GiB Arbeitsspeicher erstellt.

vLLM

vLLM unterstützt die verteilte tensorparallele Inferenz. Die Funktion wird von vLLM standardmäßig aktiviert, wenn mehr als eine GPU verfügbar ist.

Im folgenden Snippet wird gezeigt, wie Sie das für die Anleitung abgestimmte Modell Gemma 7B mit Tensorparallelität und zwei L4-GPUs optimieren:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

In GKE Autopilot-Clustern wird durch Ausführen dieses Befehls ein Pod mit den Mindestressourcenanforderungen von 21 vCPU und 78 GiB Arbeitsspeicher erstellt.

Best Practice: Optimierung des Modellspeichers

Die Optimierung der Arbeitsspeichernutzung von LLMs ist entscheidend für eine effiziente Inferenz. In diesem Abschnitt werden Optimierungsstrategien für die Aufmerksamkeitsebene vorgestellt, z. B. Paged Attention und Flash Attention. Diese Strategien verbessern die Arbeitsspeichereffizienz, was längere Eingabesequenzen und eine geringere GPU-Ruhezeit ermöglicht. In diesem Abschnitt wird auch beschrieben, wie Sie die Größe der Modellein- und ‑ausgabe an die Arbeitsspeicherbeschränkungen anpassen und für bestimmte Bereitstellungsframeworks optimieren können.

Optimierung der Aufmerksamkeitsebene

Mit Self-Attention-Schichten können Modelle den Kontext bei Sprachverarbeitungsaufgaben verstehen, da sich die Bedeutung von Wörtern je nach Kontext ändern kann. Diese Ebenen speichern jedoch Eingabetokengewichtungen, Schlüssel (K) und Werte (V) im GPU-vRAM. Wenn sich die Eingabesequenz also verlängert, führt dies zu einem quadratischen Anstieg der Größe und Rechenzeit.

Die Verwendung von KV-Caching ist besonders nützlich, wenn Sie mit langen Eingabesequenzen arbeiten, bei denen der Overhead der Self-Attention erheblich werden kann. Dieser Optimierungsansatz reduziert die Berechnungsverarbeitung auf lineare Komplexität.

Zu den speziellen Techniken zur Optimierung von Aufmerksamkeitsmechanismen in LLMs gehören:

  • Paged Attention: Paged Attention verbessert die Speicherverwaltung für große Modelle und lange Eingabesequenzen durch Auslagerungstechniken, ähnlich dem virtuellen Arbeitsspeicher des Betriebssystems. Dadurch werden Fragmentierung und Duplizierung im KV-Cache effektiv reduziert, was längere Eingabesequenzen ermöglicht, ohne dass der GPU-Arbeitsspeicher aufgebraucht wird.
  • Flash Attention: Flash Attention verringert GPU-Arbeitsspeicherengpässe, indem die Datenübertragungen zwischen GPU-RAM und L1-Cache während der Tokengenerierung minimiert werden. Dadurch werden die Inferenz- und Trainingsleistung von GPUs deutlich verbessert.

Feinabstimmung der Modelleingabe und -ausgabe

Die Arbeitsspeicheranforderungen hängen von der Größe der Eingabe und Ausgabe ab. Längere Ausgabe und mehr Kontext erfordern mehr Ressourcen. Eine kürzere Ausgabe und weniger Kontext können durch die Verwendung einer kleineren, kostengünstigeren GPU Kosten sparen.

Wählen Sie einen dieser Tabs aus, um ein Beispiel für die Feinabstimmung der Arbeitsspeicheranforderungen der Modelleingabe- und -ausgabe in den TGI- oder vLLM-Frameworks zu sehen:

TGI

Die TGI-Bereitstellungslaufzeit prüft die Arbeitsspeicheranforderungen beim Start und startet nicht, wenn der maximal mögliche Modellspeicherbedarf nicht in den verfügbaren GPU-Arbeitsspeicher passt. Durch diese Prüfung werden Abstürze aufgrund von Arbeitsspeichermangel bei arbeitsspeicherintensiven Arbeitslasten verhindert.

GKE unterstützt die folgenden TGI-Parameter zur Optimierung der Arbeitsspeicheranforderungen für Modelle:

Im folgenden Snippet wird gezeigt, wie Sie ein Gemma 7B-Modell mit optimierten Anweisungen mit einer einzelnen L4-GPU und den Parametereinstellungen --max-total-tokens=3072, --max-batch-prefill-tokens=512, --max-input-length=512 bereitstellen:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

vLLM

Konfigurieren Sie in vLLM die Kontextlänge des Modells, die sich direkt auf die KV-Cache-Größe und die GPU-RAM-Anforderungen auswirkt. Kleinere Kontextlängen ermöglichen die Verwendung kostengünstigerer GPUs. Der Standardwert ist die maximale Anzahl von Tokens, die vom Modell akzeptiert werden. Begrenzen Sie die maximale Kontextlänge bei Bedarf mit --max-model-len MAX_MODEL_LEN.

So übersteigt z. B. das für Gemma 7B optimierte Modell mit einer Standardkontextlänge von 8.192 die Arbeitsspeicherkapazität einer einzelnen NVIDIA L4-GPU. Zur Bereitstellung auf einer L4 begrenzen Sie die kombinierte Länge von Eingabeaufforderungen und Ausgaben, indem Sie --max-model-len auf einen Wert unter 640 setzen. Diese Anpassung ermöglicht es Ihnen, das Modell trotz der großen Standardkontextlänge auf einer einzelnen L4-GPU auszuführen.

Verwenden Sie das folgende Snippet, um mit dem geänderten Tokenlimit bereitzustellen:

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

Verwenden Sie den folgenden Befehl, um diese Konfiguration anzuwenden:

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

Zusammenfassung der Checkliste

Optimierungsziel Übung
Latenz
  • Leistungsstarke GPUs priorisieren: Sie sollten ein Upgrade auf GPUs mit höherer Rechenleistung und höherem Arbeitsspeicher-E/A-Durchsatz in Betracht ziehen.
  • Quantisierung untersuchen: Mit Verfahren wie der AWQ lässt sich die Latenz verbessern. Beachten Sie jedoch mögliche Einbußen bei der Genauigkeit.
Durchsatz
  • Horizontal skalieren: Erhöhen Sie die Anzahl der ausgelieferten Replikate (Pods), um die Arbeitslast zu verteilen.
  • Tensor-Parallelität verwenden: Verwenden Sie bei großen Modellen, die eine einzelne GPU-Kapazität überschreiten, die Tensor-Parallelität, um Berechnungen auf mehrere GPUs zu verteilen. Bei kleineren Modellen sollten Sie mehrere Replikate mit einer Tensorparallelität von „1“ verwenden, um den Overhead zu vermeiden.
  • Batchanfragen und quantisieren: Kombinieren Sie Anfragen und untersuchen Sie Quantisierungstechniken, die eine akzeptable Genauigkeit gewährleisten.
Kosteneffizienz
  • Kleinere Modelle auswählen: Wählen Sie Modelle in einer Familie aus, die Ihren Ressourcenlimits und Ihrem Budget entsprechen.
  • Quantisierung anwenden: Mit der Quantisierung können Sie die Arbeitsspeicheranforderungen reduzieren, insbesondere bei größeren Modellen.
  • Kontextlänge begrenzen: Mit dieser Option können Sie die Kontextlänge einschränken, um die Arbeitsspeichernutzung weiter zu senken und die Ausführung auf kleineren, kostengünstigeren GPUs zu ermöglichen.

Nächste Schritte