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 von Inferenz und Bereitstellung offener LLMs mit GPUs in 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 daran interessiert sind, ihre LLM-Arbeitslasten mit GPUs und Kubernetes zu optimieren.

Am Ende dieser Anleitung können Sie:

  • Wählen Sie Techniken zur LLM-Optimierung nach dem Training aus, darunter Quantisierung, Tensorparallelität und Speicheroptimierung.
  • Wägen Sie die allgemeinen Vor- und Nachteile ab, wenn Sie diese Optimierungstechniken in Betracht ziehen.
  • Stellen Sie offene LLM-Modelle in GKE mit Serving-Frameworks wie vLLM oder TGI mit aktivierten Optimierungseinstellungen bereit.

Übersicht über Techniken zur Optimierung der LLM-Bereitstellung

Im Gegensatz zu Nicht-KI-Arbeitslasten weisen LLM-Arbeitslasten in der Regel eine höhere Latenz und einen geringeren Durchsatz auf, da sie auf Matrixmultiplikationsvorgängen basieren. Um die Inferenzleistung von LLMs zu verbessern, können Sie spezielle Hardwarebeschleuniger (z. B. GPUs und TPUs) und optimierte Bereitstellungs-Frameworks verwenden.

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

In den Beispielen in dieser Anleitung wird das Gemma 7B-LLM zusammen mit den Serving-Frameworks vLLM oder TGI verwendet, um diese Best Practices anzuwenden. Die beschriebenen Konzepte und Funktionen gelten jedoch für die meisten beliebten offenen LLMs.

Hinweise

Bevor Sie die Beispiele in diesem Leitfaden ausprobieren, müssen Sie die folgenden Voraussetzungen erfüllen:

  1. Folgen Sie der Anleitung in diesen Leitfäden, um Zugriff auf das Gemma-Modell zu erhalten, Ihre Umgebung vorzubereiten und 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 mit der verlustbehafteten Bildkomprimierung vergleichbar ist. Sie reduziert die Modellgröße, indem Gewichte in Formaten mit geringerer Genauigkeit (8 Bit oder 4 Bit) dargestellt werden, wodurch der Speicherbedarf sinkt. Wie bei der Bildkomprimierung ist die Quantisierung jedoch ein Kompromiss: Eine kleinere Modellgröße kann zu einer geringeren Genauigkeit führen.

Es gibt verschiedene Quantisierungsmethoden, die jeweils eigene 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-Modell mit 13 Milliarden Parametern und AWQ auf das Gemma-Modell mit 7 Milliarden Parametern anwenden, können Sie die Modelle auf einer einzelnen L4-GPU anstelle von zwei L4-GPUs ohne Quantisierung bereitstellen.

Sie können die Quantisierung auch mit Tools wie AutoAWQ und AutoGPTQ durchführen. Diese Methoden können die Latenz und den 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 Serving-Framework ab, das Sie verwenden möchten. Weitere Informationen finden Sie im Quantization Guide 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 AWQ- und GPTQ-Quantisierungsmethoden sind vorab quantisierte Modelle erforderlich, während die EETQ- und bitsandbytes-Quantisierung auf jedes Modell angewendet werden kann. Weitere Informationen zu diesen Optionen finden Sie in diesem Hugging Face-Artikel.

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

Das folgende Snippet zeigt, wie Sie Gemma 7B mit bitsandbytes-Quantisierung mit 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 die folgenden Quantisierungsoptionen mit vLLM:

Wenn Sie die Modellquantisierung mit vLLM verwenden möchten, müssen die Modelle vorquantisiert werden. Legen Sie beim Starten der Laufzeit den Parameter –quantization fest.

Das folgende Snippet zeigt, wie Sie das Gemma 7B-Modell mit awq-Quantisierung mit 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 FP8 E5M2-KV-Cache-Quantisierung können Sie den Speicherbedarf des KV-Caches erheblich verringern und die Latenz verbessern, insbesondere bei großen Batchgrößen. Dies verringert jedoch die Genauigkeit der Inferenz.

Wenn Sie die FP8 E5M2-KV-Cache-Quantisierung aktivieren möchten, legen Sie den Parameter --kv-cache-dtype fp8_e5m2 fest:

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: Tensor-Parallelitä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 kostengünstige GPUs anstelle einer einzigen teuren verwenden können. Außerdem kann der Durchsatz der Modellinferenz erhöht werden. Die Tensor-Parallelität nutzt die Tatsache, dass Tensor-Operationen unabhängig voneinander für kleinere Datenblöcke ausgeführt werden können.

Weitere Informationen zu dieser Technik finden Sie im Leitfaden zu Tensor-Parallelismus von Hugging Face.

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

TGI

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

Eine Liste der Modelle, die für Tensor-Parallelität unterstützt werden, finden Sie in der Hugging Face-Dokumentation.

Das folgende Snippet zeigt, wie Sie das für die Anleitung abgestimmte Modell Gemma 7B mit Tensor-Parallelität und zwei L4-GPUs optimieren:

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

Wenn Sie diesen Befehl in GKE Autopilot-Clustern ausführen, wird ein Pod mit Mindestressourcenanforderungen von 21 vCPUs und 78 GiB Arbeitsspeicher erstellt.

vLLM

vLLM unterstützt die verteilte Tensor-parallele Inferenz. vLLM aktiviert die Funktion standardmäßig, wenn mehr als eine GPU verfügbar ist.

Das folgende Snippet zeigt, wie Sie das für die Anleitung abgestimmte Modell Gemma 7B mit Tensor-Parallelität und zwei L4-GPUs optimieren können:

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

Wenn Sie diesen Befehl in GKE Autopilot-Clustern ausführen, wird ein Pod mit Mindestressourcenanforderungen von 21 vCPUs 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 Speichereffizienz und ermöglichen längere Eingabesequenzen und eine geringere GPU-Inaktivitätszeit. 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

Self-Attention-Schichten ermöglichen es Modellen, den Kontext bei Aufgaben zur Sprachverarbeitung zu verstehen, da sich die Bedeutung von Wörtern je nach Kontext ändern kann. In diesen Layern werden jedoch Eingabetoken-Gewichtungen, Schlüssel (K) und Werte (V) im GPU-vRAM gespeichert. Wenn die Eingabesequenz länger wird, führt dies zu einem quadratischen Wachstum der Größe und der Rechenzeit.

Die KV-Zwischenspeicherung ist besonders nützlich, wenn Sie es mit langen Eingabesequenzen zu tun haben, bei denen der Overhead der Self-Attention erheblich sein kann. Dieser Optimierungsansatz reduziert die Rechenleistung auf lineare Komplexität.

Spezifische Techniken zur Optimierung von Aufmerksamkeitsmechanismen in LLMs sind:

  • 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 Leerlaufzeiten für Rechenkerne vermieden und die Inferenz- und Trainingsleistung für GPUs wird erheblich verbessert.

Feinabstimmung der Modelleingabe und -ausgabe

Die Speicheranforderungen hängen von der Eingabe- und Ausgabegröße ab. Längere Ausgaben und mehr Kontext erfordern mehr Ressourcen, während kürzere Ausgaben und weniger Kontext Kosten sparen können, da eine kleinere, günstigere GPU verwendet wird.

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 OOM-Abstürze (Out-of-Memory) bei arbeitsspeicherintensiven Arbeitslasten vermieden.

GKE unterstützt die folgenden TGI-Parameter zum Optimieren der Arbeitsspeicheranforderungen von Modellen:

Im folgenden Snippet sehen Sie, wie Sie ein Gemma 7B-Modell, das auf Anweisungen abgestimmt ist, mit einer einzelnen L4-GPU und den Parametereinstellungen --max-total-tokens=3072, --max-batch-prefill-tokens=512, --max-input-length=512 bereitstellen können:

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. Diese wirkt sich direkt auf die Größe des KV-Cache und die GPU-RAM-Anforderungen aus. Bei kürzeren Kontextlängen können kostengünstigere GPUs verwendet werden. Der Standardwert ist die maximale Anzahl von Tokens, die das Modell akzeptiert. 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. Wenn Sie auf einem L4-Gerät bereitstellen möchten, begrenzen Sie die kombinierte Länge von Prompts und Ausgaben, indem Sie --max-model-len auf einen Wert unter 640 festlegen. Durch diese Anpassung kann das Modell trotz seiner großen Standardkontextlänge auf einer einzelnen L4-GPU ausgeführt werden.

Verwenden Sie das folgende Snippet, um die Bereitstellung mit dem geänderten Tokenlimit durchzuführen:

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: Techniken wie AWQ können die Latenz verbessern, aber achten Sie auf mögliche Einbußen bei der Genauigkeit.
Durchsatz
  • Horizontal skalieren: Erhöhen Sie die Anzahl der Serving-Replikate (Pods), um die Arbeitslast zu verteilen.
  • Tensor-Parallelität verwenden: Verwenden Sie für große Modelle, die die Kapazität einer einzelnen GPU überschreiten, die Tensor-Parallelität, um Berechnungen auf mehrere GPUs zu verteilen. Bei kleineren Modellen sollten Sie mehrere Replikate mit Tensorparallelität `1` in Betracht ziehen, um Mehraufwand zu vermeiden.
  • Batchanfragen und Quantisierung: Kombinieren Sie Anfragen und nutzen Sie Quantisierungstechniken, die eine akzeptable Genauigkeit beibehalten.
Kosteneffizienz
  • Kleinere Modelle auswählen: Wählen Sie Modelle innerhalb einer Familie aus, die Ihren Ressourcenbeschränkungen und Ihrem Budget entsprechen.
  • Quantisierung anwenden: Verwenden Sie die Quantisierung, um den Speicherbedarf zu reduzieren, insbesondere bei größeren Modellen.
  • Kontextlänge begrenzen: Begrenzen Sie die Kontextlänge, um die Speichernutzung weiter zu verringern und die Ausführung auf kleineren, kostengünstigeren GPUs zu ermöglichen.

Nächste Schritte