Best Practices: Cloud Run-Worker-Pools mit GPUs

Auf dieser Seite finden Sie Best Practices zur Leistungsoptimierung bei der Verwendung eines Cloud Run-Worker-Pools mit KI-Arbeitslasten, z. B. zum Trainieren von Large Language Models (LLMs) mit Ihren bevorzugten Frameworks, zum Feinabstimmen und zum Ausführen von Batch- oder Offline-Inferenz für LLMs. So erstellen Sie einen Cloud Run-Worker-Pool, der rechenintensive Aufgaben oder die Batchverarbeitung in Echtzeit ausführen kann:
  • Verwenden Sie Modelle, die schnell geladen werden und nur minimale Transformationen in GPU-kompatible Strukturen erfordern, und optimieren Sie, wie sie geladen werden.
  • Verwenden Sie Konfigurationen, die eine maximale, effiziente, gleichzeitige Ausführung ermöglichen, um die Anzahl der GPUs zu reduzieren, die zum Ausführen einer Zielanfrage pro Sekunde erforderlich sind, und gleichzeitig die Kosten niedrig zu halten.

Empfohlene Methoden zum Laden großer ML-Modelle in Cloud Run

Google empfiehlt, ML-Modelle entweder in Container-Images zu speichern oder das Laden aus Cloud Storage zu optimieren.

Vor- und Nachteile beim Speichern und Laden von ML-Modellen

Hier finden Sie einen Vergleich der Optionen:

Modellstandort Bereitstellungszeit Entwicklungserfahrung Container-Startzeit Speicherkosten
Container-Image Langsam. Das Importieren eines Bildes mit einem großen Modell in Cloud Run dauert länger. Änderungen am Container-Image erfordern eine erneute Bereitstellung, was bei großen Images langsam sein kann. Abhängig von der Größe des Modells. Bei sehr großen Modellen sollten Sie Cloud Storage verwenden, um eine vorhersehbarere, aber langsamere Leistung zu erzielen. Möglicherweise mehrere Kopien in Artifact Registry.
Cloud Storage über das Cloud Storage FUSE-Volume bereitgestellt Schnell. Das Modell wurde beim Start des Containers heruntergeladen. Die Einrichtung ist einfach und es sind keine Änderungen am Docker-Image erforderlich. Schnell bei Netzwerkoptimierungen. Der Download wird nicht parallelisiert. Eine Kopie in Cloud Storage.
Cloud Storage, gleichzeitig heruntergeladen mit dem Google Cloud CLI-Befehl gcloud storage cp oder der Cloud Storage API, wie im Codebeispiel für gleichzeitigen Download des Transfer Manager gezeigt. Schnell. Das Modell wurde beim Start des Containers heruntergeladen. Die Einrichtung ist etwas schwieriger, da Sie entweder die Google Cloud CLI auf dem Image installieren oder Ihren Code aktualisieren müssen, um die Cloud Storage API zu verwenden. Schnell bei Netzwerkoptimierungen. Die Google Cloud CLI lädt die Modelldatei parallel herunter, was schneller ist als die FUSE-Bereitstellung. Eine Kopie in Cloud Storage.
Internet Schnell. Das Modell wurde beim Start des Containers heruntergeladen. In der Regel einfacher (viele Frameworks laden Modelle aus zentralen Repositories herunter). In der Regel schlecht und unvorhersehbar:
  • Frameworks können während der Initialisierung Modelltransformationen anwenden. Das sollten Sie zur Build-Zeit tun.
  • Der Modellhost und die Bibliotheken zum Herunterladen des Modells sind möglicherweise nicht effizient.
  • Das Herunterladen aus dem Internet birgt ein Zuverlässigkeitsrisiko. Ihre Worker-Pools können nicht gestartet werden, wenn das Downloadziel nicht verfügbar ist. Außerdem kann sich das heruntergeladene zugrunde liegende Modell ändern, was die Qualität verringert. Wir empfehlen, die Dateien in Ihrem eigenen Cloud Storage-Bucket zu hosten.
Abhängig vom Anbieter des Modell-Hostings.

Modelle in Container-Images speichern

Wenn Sie das ML-Modell im Container-Image speichern, profitiert das Laden des Modells von der optimierten Container-Streaming-Infrastruktur von Cloud Run. Das Erstellen von Container-Images, die ML-Modelle enthalten, ist jedoch ein ressourcenintensiver Prozess, insbesondere bei der Arbeit mit großen Modellen. Insbesondere kann der Build-Prozess durch den Netzwerkdurchsatz beeinträchtigt werden. Wenn Sie Cloud Build verwenden, empfehlen wir, eine leistungsstärkere Build-Maschine mit erhöhter Rechen- und Netzwerkleistung zu verwenden. Dazu erstellen Sie ein Image mit einer Build-Konfigurationsdatei, die die folgenden Schritte enthält:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'IMAGE', '.']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'IMAGE']
images:
- IMAGE
options:
 machineType: 'E2_HIGHCPU_32'
 diskSizeGb: '500'
 

Sie können eine Modellkopie pro Bild erstellen, wenn sich die Ebene mit dem Modell zwischen den Bildern unterscheidet (unterschiedlicher Hash). Es können zusätzliche Artifact Registry-Kosten anfallen, da es möglicherweise eine Kopie des Modells pro Image gibt, wenn Ihre Modellebene für jedes Image eindeutig ist.

Modelle in Cloud Storage speichern

Wenn Sie das Laden von ML-Modellen aus Cloud Storage optimieren möchten, entweder über Cloud Storage-Volumen-Bereitstellungen oder direkt über die Cloud Storage API oder die Befehlszeile, müssen Sie Direct VPC mit der Einstellung für ausgehenden Traffic auf all-traffic und privaten Google-Zugriff verwenden.

Gegen Aufpreis können Sie mit Anywhere Cache die Latenz beim Laden von Modellen reduzieren, indem Sie Daten effizient auf SSDs für schnellere Lesevorgänge zwischenspeichern.

Um die Lesezeiten für Modelle zu verkürzen, können Sie die folgenden Bereitstellungsoptionen verwenden, um Cloud Storage FUSE-Funktionen zu aktivieren:

  • cache-dir: Aktivieren Sie die Funktion für das Datei-Caching mit einer In-Memory-Volume-Bereitstellung, die als zugrunde liegendes Verzeichnis zum Speichern von Dateien verwendet wird. Legen Sie den Wert der Mount-Option cache-dir auf den Namen des In-Memory-Volumes im Format cr-volume:{volume name} fest. Wenn Sie beispielsweise ein In-Memory-Volume mit dem Namen in-memory-1 haben, das Sie als Cacheverzeichnis verwenden möchten, geben Sie cr-volume:in-memory-1 an. Wenn dieser Wert festgelegt ist, können Sie auch andere file-cache-Flags für die Cachekonfiguration festlegen.
  • enable-buffered-read: Setzen Sie das Feld enable-buffered-read auf true, um Teile eines Cloud Storage-Objekts asynchron in einen Arbeitsspeicher-Puffer vorab abzurufen. Dadurch können nachfolgende Lesevorgänge aus dem Puffer bedient werden, ohne dass Netzwerkaufrufe erforderlich sind. Wenn Sie dieses Feld konfigurieren, können Sie auch das Feld read-global-max-blocks festlegen, um die maximale Anzahl an Blöcken zu konfigurieren, die für gepufferte Lesevorgänge für alle Datei-Handles verfügbar sind.

Wenn sowohl cache-dir als auch enable-buffered-read verwendet werden, hat cache-dir Vorrang. Wenn Sie eine dieser Funktionen aktivieren, wird die Ressourcenabrechnung des Cloud Storage FUSE-Prozesses auf die Container-Speicherlimits angerechnet. Erhöhen Sie das Arbeitsspeicherlimit des Containers. Hier finden Sie eine Anleitung zum Konfigurieren von Arbeitsspeicherlimits.

Modelle aus dem Internet laden

Um das Laden von ML-Modellen aus dem Internet zu optimieren, leiten Sie den gesamten Traffic über das VPC-Netzwerk weiter, wobei der Wert der Egress-Einstellung auf all-traffic festgelegt ist, und richten Sie Cloud NAT ein, um das öffentliche Internet mit hoher Bandbreite zu erreichen.

Erwägungen zu Build, Bereitstellung, Laufzeit und Systemdesign

In den folgenden Abschnitten werden Überlegungen zu Build, Bereitstellung, Laufzeit und Systemdesign beschrieben.

Zur Build-Zeit

In der folgenden Liste finden Sie einige Aspekte, die Sie bei der Planung Ihres Builds berücksichtigen sollten:

  • Wählen Sie ein gutes Basis-Image aus. Sie sollten mit einem Image aus den Deep Learning Containern oder der NVIDIA-Container Registry für das verwendete ML-Framework beginnen. Diese Images enthalten die neuesten leistungsrelevanten Pakete. Wir raten davon ab, ein benutzerdefiniertes Image zu erstellen.
  • Wählen Sie 4-Bit-quantisierte Modelle aus, um die Nebenläufigkeit zu maximieren, sofern Sie nicht nachweisen können, dass sie sich auf die Ergebnisqualität auswirken. Durch die Quantisierung entstehen kleinere und schnellere Modelle, wodurch der für die Modellbereitstellung benötigte GPU-Speicher reduziert und die Parallelität zur Laufzeit erhöht wird. Idealerweise sollten die Modelle mit der Zielbittiefe trainiert werden, anstatt auf diese herunterquantisiert zu werden.
  • Wählen Sie ein Modellformat mit schnellen Ladezeiten aus, um die Containerstartzeit zu minimieren, z. B. GGUF. Diese Formate spiegeln den Zielquantisierungstyp genauer wider und erfordern weniger Transformationen beim Laden auf die GPU. Aus Sicherheitsgründen sollten Sie keine Checkpoints im Pickle-Format verwenden.
  • LLM-Caches beim Build erstellen und vorwärmen Starten Sie das LLM auf dem Build-Computer, während Sie das Docker-Image erstellen. Aktivieren Sie das Prompt-Caching und geben Sie häufig verwendete oder Beispiel-Prompts ein, um den Cache für die Verwendung in der Praxis vorzubereiten. Speichern Sie die Ausgaben, die generiert werden, damit sie zur Laufzeit geladen werden können.
  • Speichern Sie Ihr eigenes Inferenzmodell, das Sie während der Erstellung generieren. Das spart im Vergleich zum Laden weniger effizient gespeicherter Modelle und zum Anwenden von Transformationen wie der Quantisierung beim Containerstart viel Zeit.

Bei der Bereitstellung

Die folgende Liste enthält Aspekte, die Sie bei der Planung der Bereitstellung berücksichtigen müssen:

  • GPU-Worker-Pools können nicht automatisch skaliert werden. Die GPU wird Ihnen auch dann in Rechnung gestellt, wenn auf ihr keine Prozesse ausgeführt werden.
  • CPU und Arbeitsspeicher für Worker-Pools werden anders berechnet als für Dienste und Jobs. Die GPU-SKU wird jedoch genauso abgerechnet wie Dienste und Jobs.

Während der Laufzeit

  • Verwalten Sie die unterstützte Kontextlänge aktiv. Je kleiner das unterstützte Kontextfenster ist, desto mehr Abfragen können Sie parallel ausführen. Die Details dazu hängen vom Framework ab.
  • Verwenden Sie die LLM-Caches, die Sie beim Build generiert haben. Geben Sie dieselben Flags an, die Sie während der Build-Zeit verwendet haben, als Sie den Prompt- und Präfix-Cache generiert haben.
  • Laden Sie das gespeicherte Modell, das Sie gerade erstellt haben. Einen Vergleich dazu, wie das Modell geladen wird, finden Sie unter Vor- und Nachteile beim Speichern und Laden von Modellen.
  • Verwenden Sie einen quantisierten Schlüssel/Wert-Cache, sofern Ihr Framework dies unterstützt. Dadurch kann der Speicherbedarf pro Anfrage gesenkt und mehr Parallelität konfiguriert werden. Dies kann sich jedoch auch auf die Qualität auswirken.
  • Passen Sie die Menge des GPU-Speichers an, der für Modellgewichte, Aktivierungen und Key-Value-Caches reserviert werden soll. Stellen Sie den Wert so hoch wie möglich ein, ohne dass ein Fehler aufgrund von zu wenig Arbeitsspeicher auftritt.
  • Prüfen Sie, ob Ihr Framework Optionen zur Verbesserung der Containerstartleistung bietet, z. B. durch Parallelisierung des Modellladens.

Auf Systemdesignebene

  • Fügen Sie gegebenenfalls semantische Caches hinzu. In einigen Fällen kann das Zwischenspeichern ganzer Anfragen und Antworten eine gute Möglichkeit sein, die Kosten für häufige Anfragen zu begrenzen.
  • Varianz in den Präambeln kontrollieren Prompt-Caches sind nur nützlich, wenn sie die Prompts in der richtigen Reihenfolge enthalten. Caches werden effektiv als Präfix-Cache gespeichert. Einfügungen oder Änderungen in der Sequenz bedeuten, dass sie entweder nicht im Cache gespeichert oder nur teilweise vorhanden sind.