Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Disaggregiertes Vorfüllen und Dekodieren für Rückschlüsse HyperPod
Disaggregated Prefill and Decode (DPD) trennt die beiden Phasen der LLM-Inferenz, Prefill und Decode, auf dedizierte GPU-Pools und überträgt den Key-Value (KV) -Cache zwischen ihnen über Elastic Fabric Adapter (EFA) mithilfe von GPU-Direct Remote Direct Memory Access (RDMA).
Wenn Prefill und Decode auf derselben GPU (am selben Ort) ausgeführt werden, kann eine einzige Long-Context-Anfrage die Token-Streams während des Fluges für andere Clients blockieren und die Latenz pro Token unter Last erhöhen. DPD beseitigt diese Störung, indem es auf einer Gruppe von GPUs rechnergebundenes Prefill und auf einem anderen die speicherbandbreitengebundene Decodierung ausführt. Dies sorgt für eine besser vorhersehbare Latenz bei gemischtem Datenverkehr und ermöglicht es Ihnen, jede Phase unabhängig zu skalieren.
Der Inferenzoperator kümmert sich um die Orchestrierung. Dazu gehören die Bereitstellung des Routers, die Verkabelung von Prefill- und Decode-Pods über LMCache und NIXL sowie die Integration mit Observability. HyperPod Sie können DPD aktivieren, indem Sie derselben Ressource, die Sie bereits für Inferenzendpunkte verwenden, einen pdSpec Abschnitt hinzufügen. InferenceEndpointConfig
Wenn DPD hilft
DPD bietet den größten Nutzen, wenn alle folgenden Bedingungen vorliegen:
-
Große Modelle mit hoher Dichte — Parameter über 70 B (z. B. Llama 3.3 70B).
-
Lange Eingaben — über 4.000 Eingabe-Token. Inter-token Die Verbesserung der Latenz (ITL) skaliert mit der Eingabelänge, da längere Vorbefüllungen zu mehr Decodierungsstörungen führen, wenn sie gleichzeitig platziert werden.
-
Dauerhafte Parallelität — mehr als 2 Anfragen pro Sekunde. Ohne gleichzeitige Anfragen, die um dieselbe GPU konkurrieren, gibt es nichts, was disaggregiert werden könnte.
-
Moderate oder lange Ausgaben — über 256 Ausgangstoken. Mehr Output-Token bedeuten einen größeren kumulativen Vorteil einer stabilen Latenz pro Token.
Wenn Ihr Workload kurze Eingaben, geringe Parallelität oder kleine Modelle verwendet, ist eine standardmäßige Colocation-Bereitstellung einfacher und funktioniert gut.
Voraussetzungen
Bevor Sie Inferenzendpunkte bereitstellen, die Disaggregated Prefill and Decode verwenden, müssen Sie die folgenden Komponenten in Ihrer lokalen Entwicklungsumgebung einrichten:
-
Zugriff auf Ihren HyperPod Amazon EKS-Cluster über kubectl
-
Hugging
Face-Token, das den Lesezugriff auf den jeweiligen Modell-Checkpoint ermöglicht. Dies ist nicht erforderlich, wenn sich der Modell-Checkpoint bereits in einem Amazon S3-Bucket befindet. -
Ein Worker-Image, das vLLM, LMCache, NVIDIA NIXL und den EFA-Libfabric-Provider umfasst. Die folgenden Image-Optionen werden unterstützt:
-
DLC:
public.ecr.aws/deep-learning-containers/vllm:server-hyperpod-cuda-v1.1 -
LM-Cache:
lmcache/vllm-openai:v0.4.3
Beide Images enthalten LMCache 0.4.3, vLLM 0.19.0 und NIXL 1.0.0.
-
-
HyperPod Inference Operator Version 3.2 oder höher ist installiert. DPD wird in früheren Versionen nicht unterstützt. Der Operator ist standardmäßig in neu erstellten HyperPod Amazon EKS-Clustern installiert. Wenn Sie beabsichtigen, einen vorhandenen Cluster zu verwenden, folgen Sie den Installationsanweisungen unterRichten Sie Ihre HyperPod Cluster für die Modellbereitstellung ein. Überprüfen Sie Ihre Version:
kubectl get deployment hyperpod-inference-operator-controller-manager \ -n hyperpod-inference-system \ -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].image}{"\n"}'
Wichtig
Disaggregated Prefill and Decode erfordert EFA-capable Instanzen mit RDMA-Unterstützung. GPU-Direct Die folgenden Instanztypen werden unterstützt:ml.p5.48xlarge,,,. ml.p5e.48xlarge ml.p5en.48xlarge ml.p6-b200.48xlarge ml.p6-b300.48xlarge Andere Instanztypen werden für DPD nicht unterstützt.
Stellen Sie einen DPD-Endpunkt bereit
Die meisten InferenceEndpointConfig Felder werden mit Nicht-DPD-Endpunkten gemeinsam genutzt und sind in dokumentiert. Bereitstellen von Grundlagenmodellen und maßgeschneiderten, optimierten Modellen Um DPD zu aktivieren, fügen Sie Ihrem Manifest die folgenden Abschnitte hinzu.
Prefill-Decode Spezifikation: PDSpec
Deklariert die prefill/decode Topologie und gibt Argumente an. Durch das Vorhandensein dieses Felds wird der Endpunkt disaggregiert: Der Operator erstellt separate Deployments für das Vorfüllen und Dekodieren und verbindet sie über den Router und das LMCache-PD-Backend miteinander.
pdSpec: prefillSpec: replicas: 1 resources: limits: nvidia.com/gpu: ${GPUS_PER_NODE} requests: nvidia.com/gpu: ${GPUS_PER_NODE} args: - "--gpu-memory-utilization" - "0.75" decodingSpec: replicas: 1 resources: limits: nvidia.com/gpu: ${GPUS_PER_NODE} requests: nvidia.com/gpu: ${GPUS_PER_NODE} routingThreshold: 4096
replicas-
Vorfüllen und Dekodieren unabhängig voneinander skalieren.
resources-
Wird auf die Pod-Spezifikation der Rolle angewendet. Top-level
worker.resourceswird für DPD-Pods ignoriert; rollenspezifische Werte werden überschrieben. routingThreshold-
Schwellenwert für die Tokenlänge, der Anfragen an den disaggregierten Pfad weiterleitet. Anfragen, die diesen Schwellenwert nicht erreichen, umgehen den Prefiller und werden direkt an den Decoder weitergeleitet.
args-
vLLM-Flags, die für diese Rolle spezifisch sind.
worker.argsBeim Start zusammengeführt: Bereits vorhandene Flagsworker.argswerden durch den Wert pro Rolle ersetzt; Flags, die nicht vorhanden sind, werden angehängt.
DPD-Umgebungsvariablen: Umgebungsvariablen
Diese Umgebungsvariablen werden identisch sowohl auf den Prefiller- als auch auf den Decoder-Container angewendet; es gibt kein env-var-Feld pro Rolle. Für rollenspezifisches Verhalten verwenden Sie stattdessen. pdSpec.{prefillSpec,decodingSpec}.args
environmentVariables: - name: PD_BUFFER_SIZE value: "8589934592" - name: LMCACHE_SAVE_DECODE_CACHE value: "False" - name: PYTHONHASHSEED value: "0"
PD_BUFFER_SIZE(8 GiB)-
GPU-Puffer, der auf dem Decoder für eingehende KV-Cache-Übertragungen reserviert ist und pro Rang dimensioniert ist. Für Lama 70B mit TP=8 ist der KV-Cache jedes Tokens ungefähr 40 KB pro Rang groß, sodass eine 6000-Token-Aufforderung ungefähr 0,23 GB pro Rang belegt und 8 GiB ungefähr 35 solcher Übertragungen während des Fluges aufnehmen können. Wenn der Puffer die Kapazität überschreitet, protokolliert der Decoder und auf den Clients treten Latenzspitzen auf.
Failed to allocate memory object, retrying...Auf 16/32 GiB erhöhen oder beidecodingSpec.replicasBedarf skalieren. LMCACHE_SAVE_DECODE_CACHE:"False"-
Deaktiviert redundantes L1-Caching auf dem Decoder. Der Prefiller ist die Quelle der Wahrheit für Cache-Treffer.
PYTHONHASHSEED:"0"-
LMCache verwendet Pythons eingebaute Funktion
hash()zur Berechnung von Prompt-Token-Cache-Schlüsseln. Python randomisiert diesen Hash-Seed standardmäßig pro Prozess, sodass identische Eingabeaufforderungen beim Prefiller und Decoder unterschiedliche Schlüssel erzeugen und Lookups fehlschlagen. Durch das Anheften des Seeds stimmen die Schlüssel auf allen Pods überein.
Konfigurieren Sie die Routing-Strategie
intelligentRoutingSpecIn diesem Abschnitt wird die Routing-Strategie festgelegt, mit der der DPD-Router für jede Anfrage einen Prefiller auswählt. Der Router wird automatisch erstellt, wenn er vorhanden pdSpec ist. Dieser Abschnitt ist optional und standardmäßig auf eingestellt. prefixaware
intelligentRoutingSpec: enabled: true routingStrategy: prefixaware
DPD kann auch in intelligentes Routing und KV-Caching integriert werden. Weitere Informationen finden Sie unter Konfigurieren Sie KV-Caching und intelligentes Routing.
Mit einem einzigen Prefill-Replikat werden alle Strategien an dieses Replikat weitergeleitet. Die Auswahl wirkt sich nur auf das Verhalten aus, wenn: prefillSpec.replicas > 1
-
Verwenden Sie für ein einzelnes Prefill-Replikat die Option
prefixaware(Standardeinstellung), um die KV-Cache-Treffer zu maximieren, wenn Aufforderungen gemeinsame Präfixe wie Systemansagen oder Chatverlauf haben. -
Verwenden Sie diese Option für mehrere Prefill-Replikate, um die Last gleichmäßig auf die Replikate
roundrobinzu verteilen und zu vermeiden, dass ein einzelnes Prefiller im Hotspot-Modus erkannt wird.
Vollständiges Beispiel
Das folgende Manifest stellt Llama 3.3 70B auf zwei ml.p5.48xlarge Instances bereit (eine Prefiller, eine Decoder):
apiVersion: inference.sagemaker.aws.amazon.com/v1 kind: InferenceEndpointConfig metadata: name: dpd-test namespace: default spec: endpointName: dpd-test instanceType: ml.p5.48xlarge invocationEndpoint: v1/chat/completions modelName: Llama-3.3-70B-Instruct modelSourceConfig: modelSourceType: s3 modelLocation: Llama-3.3-70B-Instruct s3Storage: bucketName: <YOUR_BUCKET> region: <YOUR_REGION> loadBalancer: healthCheckPath: /health metrics: enabled: true kvCacheSpec: enableL1Cache: true intelligentRoutingSpec: enabled: true routingStrategy: prefixaware pdSpec: prefillSpec: replicas: 1 resources: requests: nvidia.com/gpu: "8" limits: nvidia.com/gpu: "8" decodingSpec: replicas: 1 resources: requests: nvidia.com/gpu: "8" limits: nvidia.com/gpu: "8" routingThreshold: 4096 worker: image: public.ecr.aws/deep-learning-containers/vllm:server-hyperpod-cuda-v1.1 args: - "--model" - "/opt/ml/model" - "--host" - "0.0.0.0" - "--port" - "8000" - "--tensor-parallel-size" - "8" - "--max-model-len" - "16384" - "--gpu-memory-utilization" - "0.75" modelInvocationPort: name: http containerPort: 8000 modelVolumeMount: name: model-weights mountPath: /opt/ml/model resources: requests: cpu: "96" memory: 1024Gi nvidia.com/gpu: "8" limits: cpu: "96" memory: 1024Gi nvidia.com/gpu: "8" environmentVariables: - name: HF_HOME value: /tmp/hf_home - name: PD_BUFFER_SIZE value: "8589934592" - name: LMCACHE_SAVE_DECODE_CACHE value: "False" - name: PYTHONHASHSEED value: "0"
Wenden Sie das Manifest an:
kubectl apply -f inference_endpoint_dpd_config.yaml
Überprüfen der Bereitstellung
Das Abrufen von Bildern und das Laden des Modells dauern mehrere Minuten. Pod-Status überwachen:
kubectl get pods -A \ | grep -E "prefill-|decode-|router"
Eine fehlerfreie Bereitstellung zeigt:
NAMESPACE NAME READY STATUS RESTARTS AGE default prefill-dpd-test-XXXX 3/3 Running 0 7m default decode-dpd-test-XXXX 3/3 Running 0 7m hyperpod-inference-system dpd-test-router-XXXX 2/2 Running 0 7m
Jeder Modell-Pod hat 3 Container (vLLM-Worker, Nginx-Reverse-Proxy, Collector). OpenTelemetry Der Router-Pod hat 2 Container (Router, Collector). OpenTelemetry Überprüfen Sie den InferenceEndpointConfig Status:
kubectl get inferenceendpointconfig dpd-test -n default \ -o jsonpath='{.status.conditions[0].message}{"\n"}'
Erwartete Leistung: DPD prefill and decode deployments are
ready
Überprüfen Sie die DPD-Rollen
Bestätigen Sie die Prefiller-Berichte sender und die Decoder-Berichte. receiver Dies ist das wichtigste Startsignal — wenn beide Pods dieselbe Rolle melden oder keiner von beiden die Leitung druckt, hat der Bediener DPD nicht korrekt verkabelt.
PREFILL_POD=$(kubectl get pod -n ${NAMESPACE} \ -l 'inference.sagemaker.aws.amazon.com/dpd-role=prefill' \ -o jsonpath='{.items[0].metadata.name}') DECODE_POD=$(kubectl get pod -n ${NAMESPACE} \ -l 'inference.sagemaker.aws.amazon.com/dpd-role=decode' \ -o jsonpath='{.items[0].metadata.name}') kubectl logs $PREFILL_POD -n ${NAMESPACE} -c prefill-${DEPLOYMENT_NAME} \ | grep -oE "'pd_role': '[a-z]+'" | sort -u kubectl logs $DECODE_POD -n ${NAMESPACE} -c decode-${DEPLOYMENT_NAME} \ | grep -oE "'pd_role': '[a-z]+'" | sort -u
Erwartete Ausgabe:
'pd_role': 'sender' 'pd_role': 'receiver'
Rufen Sie den Endpunkt auf
Sobald der Endpunkt bereit ist, senden Sie eine kurze und eine lange Aufforderung, beide Routingpfade zu testen. Überprüfen Sie dann die Protokolle, um die KV-Übertragung über EFA zu bestätigen.
PREFILL_POD=$(kubectl get pod -n ${NAMESPACE} \ -l 'inference.sagemaker.aws.amazon.com/dpd-role=prefill' \ -o jsonpath='{.items[0].metadata.name}') DECODE_POD=$(kubectl get pod -n ${NAMESPACE} \ -l 'inference.sagemaker.aws.amazon.com/dpd-role=decode' \ -o jsonpath='{.items[0].metadata.name}') ROUTER_POD=$(kubectl get pods -n hyperpod-inference-system -o name \ | grep -- "${DEPLOYMENT_NAME}-${NAMESPACE}-router" | head -1) ROUTER_URL=http://${DEPLOYMENT_NAME}-${NAMESPACE}-routing-service.hyperpod-inference-system.svc.cluster.local:443/v1/chat/completions
Kurze Aufforderung (unter dem Schwellenwert, direkt zum Decoder)
Anfragen mit weniger Tokens routingThreshold umgehen den Prefiller und gehen direkt zum Decoder:
kubectl run curl-short --rm -it --image=curlimages/curl --restart=Never -- \ curl -s -k -X POST "$ROUTER_URL" \ -H "Content-Type: application/json" \ -d '{ "model": "/opt/ml/model", "messages": [{"role": "user", "content": "What is disaggregated prefill-decode in one sentence?"}], "max_tokens": 80, "temperature": 0.0 }'
Lange Eingabeaufforderung (überschreitet den Schwellenwert, DPD-Pfad)
Anfragen, die den Schwellenwert überschreiten, werden zur KV-Cache-Berechnung durch den Prefiller geleitet und dann an den Decoder zur Token-Generierung weitergeleitet:
kubectl run curl-long --rm -it --image=curlimages/curl --restart=Never -- sh -c ' LONG="" i=0; while [ $i -lt 600 ]; do LONG="${LONG}The quick brown fox jumps over the lazy dog. "; i=$((i+1)); done curl -s -k -X POST "'"$ROUTER_URL"'" \ -H "Content-Type: application/json" \ -d "{\"model\":\"/opt/ml/model\",\"messages\":[{\"role\":\"user\",\"content\":\"${LONG}\"}],\"max_tokens\":30,\"temperature\":0.0}" '
Überprüfen Sie die KV-Übertragung
Bestätigen Sie nach dem Senden einer langen Aufforderung, dass der KV-Cache übertragen wurde, indem Sie die Decoder-Protokolle überprüfen:
kubectl logs $DECODE_POD -n ${NAMESPACE} -c decode-${DEPLOYMENT_NAME} \ | grep -E "Retrieved.*tokens.*throughput" | tail -2
Erwartete Ausgabe (eine Zeile pro TP-Rang):
[Worker_TP5] [LMCache INFO] [req_id=cmpl-...] Retrieved 6035 out of 6035 required tokens (from 6035 total tokens). size: 0.2344 gb, cost 1.3304 ms, throughput: 176.1686 GB/s
Retrieved N out of N required tokensmit N > 0 bestätigt, dass der KV-Cache den NIXL-Kanal erfolgreich überquert hat. Falls Sie feststellenRetrieved 0 out of N, dass der Decoder auf die lokale Neuberechnung zurückgegriffen hat — siehe. Probleme bei der Bereitstellung von Disaggregated Prefill and Decode (DPD)
Sie können die Routing-Entscheidung auch in den Router-Protokollen überprüfen:
kubectl logs $ROUTER_POD -n hyperpod-inference-system -c router-container --tail=20 \ | grep -E "Conditional routing"
Für die lange Eingabeaufforderung sollten Sie Folgendes sehen:
[INFO] Conditional routing: estimated_tokens=6750, threshold=4096, disaggregate=True
Für die kurze Eingabeaufforderung:
[INFO] Conditional routing: estimated_tokens=12, threshold=4096, disaggregate=False
Anmerkung
Um über einen SageMaker AI-KI-Endpunkt aufzurufen, geben Sie endpointName Ihren InferenceEndpointConfig ein. Wenn nicht gesetzt, endpointName wird kein SageMaker AI-KI-Endpunkt erstellt und es ist nur ein direkter ALB-Aufruf verfügbar.
Beobachtbarkeit
Aktivieren Sie Metriken, indem metrics.enabled: true Sie Ihre eingebenInferenceEndpointConfig. DPD-Metriken sind im HyperPod Inferenz-Dashboard verfügbar. Weitere Informationen finden Sie unter Implementierung der Beobachtbarkeit von Inferenzen auf Clustern HyperPod.
Die folgenden DPD-specific Metriken sind verfügbar:
| Metrik | Description |
|---|---|
| E2E TTFT | Gesamtzeit bis zum ersten Token (Vorfüllen + KV-Übertragung + Routing) |
| TTFT vorab ausfüllen | Prefiller-only Latenz |
| Warteschlange vorab ausfüllen | Anzahl der Anfragen, die auf das Vorfüllen warten |
| Warteschlange dekodieren | Anzahl der Anfragen, die auf den Decoder warten |
| Zeit für das Vorfüllen | Zeit, die für die Berechnung des Vorfüllvorgangs aufgewendet wurde |
| Latenz dekodieren | Per-token Ausgangslatenz (TPOT) |
| KV-Übertragungszeit | Zeit für die Übertragung des KV-Cache vom Prefiller zum Decoder |
| Das DPD-Routing zählt | Disaggregierte Anfragen im Vergleich zu Fallback-Anfragen (unter dem Schwellenwert) |
Optimieren Sie Ihre DPD-Bereitstellung
Die folgende Tabelle bietet eine Kurzreferenz zur Optimierung von DPD auf der Grundlage der Symptome, die Sie in Ihrem Metrik-Dashboard beobachten.
| Config | Was macht es | Standard | Wann muss man stimmen |
|---|---|---|---|
pdSpec.routingThreshold |
Mindestanzahl der Eingabe-Tokens, die durch den Prefiller geleitet werden müssen. Anfragen unter diesem Schwellenwert werden direkt an den Decoder weitergeleitet. | 4096 |
Die Standardeinstellung funktioniert für die meisten Workloads gut. Eine zu niedrige Einstellung erhöht die TTFT aufgrund unnötiger KV-Übertragungen bei kurzen Eingabeaufforderungen. Eine zu hohe Einstellung schränkt die TPOT-Verbesserung ein, da weniger Anfragen den DPD-Pfad verwenden. |
pdSpec.prefillSpec.replicas |
Anzahl der Prefill-Pods. | 1 |
Erhöhen Sie die Anzahl, wenn die Warteschlange für das Vorfüllen hoch ist, um die TTFT beim Vorfüllen zu verbessern. |
PD_BUFFER_SIZE |
Decoder-GPU-Puffer für eingehende KV-Übertragungen (pro Rang). 8 GiB bietet Platz für etwa 35 K-token Transfers während des Fluges für 70 B bei TP=8. | "8589934592"(8 GiB) |
Erhöhen Sie, um mehr gleichzeitige KV-Übertragungen zu verarbeiten. Verringern Sie, wenn Speicherprobleme auftreten. Beim Erhöhen müssen Sie möglicherweise den Decoder --gpu-memory-utilization einschalten, um GPU-Speicher für den größeren Puffer freizugeben. |
--gpu-memory-utilization |
Bruchteil des GPU-Speichers, den vLLM für Gewichtungen, Aktivierungen und KV-Cache verwendet. | 0.75 |
Erhöhen Sie den Wert, um mehr KV-Cache-Headroom bei langen Eingängen zu erhalten. Risiko: Prefiller-OOM, da Prefill auch Speicher für Aktivierungen benötigt. Testen Sie mit Ihrer tatsächlichen eingegebenen Längenverteilung. |
--max-num-seqs |
Maximale Anzahl gleichzeitiger Sequenzen pro Worker-Batch. | 16(Vorfüller), 32 (Decoder) |
Erhöhen, um unter Last besser dosieren zu können. Senken Sie, wenn Sie am Prefiller auf OOM drücken. Eingestellt pro Rolle über. pdSpec.{prefillSpec,decodingSpec}.args |
intelligentRoutingSpec.routingStrategy |
Wie der Router einen Prefiller auswählt, wenn mehrere Replikate vorhanden sind. | prefixaware |
Wird verwendetroundrobin, um die Last gleichmäßig auf mehrere Prefiller-Replikate zu verteilen. Verwenden Sie prefixaware oder kvaware mit einem einzelnen Prefiller oder wenn Prompts gemeinsame Präfixe haben (Systemansagen, Chatverlauf), um die Cache-Treffer zu maximieren. |
Testen Sie mit Ihrer tatsächlichen Arbeitslast und der Verteilung der Eingabelänge.
Um Konfigurationsänderungen anzuwenden, bearbeiten Sie Ihre Bereitstellungs-YAML und wenden Sie erneut an:
kubectl apply -f inference_endpoint_dpd_config.yaml
Bekannte Beschränkungen
-
DPD wird für Modelle mit hoher Dichte und 70 B oder mehr Parametern empfohlen. Kleinere Modelle und Mixture-of-Experts Modelle profitieren in der Regel nicht von einer Disaggregation.
-
Die aktuelle Version unterstützt eine einzelne Decodierbereitstellung pro Endpunkt. Die Unterstützung mehrerer Decode-Bereitstellungen ist für eine zukünftige Version geplant.
-
Die Leistung wird für bis zu 64 gleichzeitige Anfragen auf ml.p5.48xlarge mit Llama 3.3 70B überprüft.
-
Um von einer DPD-Bereitstellung zu einer standardmäßigen Bereitstellung an einem Standort zurückzukehren, wenden Sie eine neue ohne an.
InferenceEndpointConfigpdSpec
Informationen zur Problembehandlung bei DPD-Bereitstellungen finden Sie unter. Probleme bei der Bereitstellung von Disaggregated Prefill and Decode (DPD)