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 Inferenz HyperPod
Disaggregated Prefill and Decode (DPD) trennt die beiden Phasen der LLM-Inferenz, Vorfüllen und Dekodieren, auf dedizierte GPU-Pools und überträgt den Schlüsselwert-Cache (KV) zwischen ihnen über den Elastic Fabric Adapter (EFA) mithilfe von Remote Direct Memory Access (RDMA). GPU-Direct
Wenn Prefill und Decoding auf derselben GPU (Colocated) ausgeführt werden, kann eine einzelne Anfrage mit langem Kontext dazu führen, dass Token-Streams während des Fluges für andere Clients blockiert werden, was die Latenz pro Token unter Last erhöht. DPD beseitigt diese Interferenz, indem es auf einem Satz von GPUs rechengebundenes Prefill und auf einem anderen eine speicherbandbreitengebundene Dekodierung ausführt. Dadurch wird bei gemischtem Traffic eine vorhersehbarere Latenz erzielt und Sie können jede Phase unabhängig voneinander skalieren.
Der Inferenzoperator kümmert sich um die Orchestrierung. Dazu gehören die Bereitstellung des Routers, die Verkabelung von Prefill- und Decoder-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 der folgenden Bedingungen erfüllt sind:
-
Modelle mit großer Dichte — 70B+ Parameter (zum Beispiel Llama 3.3 70B).
-
Lange Eingaben — über 4.000 Eingabe-Token. Inter-token Die Verbesserung der Latenz (ITL) skaliert mit der Länge der Eingabe, da längere Vorfüllungen bei der gleichzeitigen Erfassung zu mehr Decodierungsstörungen führen.
-
Dauerhafte Parallelität — mehr als 2 Anfragen pro Sekunde. Ohne gleichzeitige Anfragen, die um dieselbe GPU konkurrieren, gibt es nichts, was auseinanderfallen könnte.
-
Moderate oder lange Ausgaben — mehr als 256 Ausgabetoken. Mehr Ausgabetoken bedeuten mehr kumulativen Nutzen aus einer stabilen Latenz pro Token.
Wenn Ihr Workload kurze Eingaben hat, wenig Parallelität aufweist oder kleine Modelle verwendet, ist eine standardmäßige Colocation-Bereitstellung einfacher und bietet eine gute Leistung.
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 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 S3-Bucket befindet. -
Ein Worker-Image, das vLLM, LMCache, NVIDIA NIXL und den EFA libfabric-Anbieter umfasst. Die folgenden Image-Optionen werden unterstützt:
-
DLC:
public.ecr.aws/deep-learning-containers/vllm:server-hyperpod-cuda-v1.1 -
LMCache:
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 unterEinrichtung Ihrer HyperPod Cluster für die Modellbereitstellung. Ü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 Instances 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 an Endgeräte weitergegeben, die nicht von DPD stammen, 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 spezifiziert Argumente. Durch das Vorhandensein dieses Felds wird der Endpunkt disaggregiert: Der Operator erstellt separate Deployments zum Vorfüllen und Dekodieren und verkabelt 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-
Skalieren Sie das Vorfüllen und Dekodieren unabhängig voneinander.
resources-
Wird auf die Pod-Spezifikation der Rolle angewendet. Top-level
worker.resourceswird für DPD-Pods ignoriert; Werte pro Rolle haben Vorrang. 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-
Für diese Rolle spezifische vLLM-Flags.
worker.argsBeim Start mit zusammengeführt: Bereits vorhandene Flagsworker.argswerden durch den Wert pro Rolle ersetzt; nicht vorhandene Flags werden angehängt.
DPD-Umgebungsvariablen: Umgebungsvariablen
Diese Umgebungsvariablen werden sowohl auf den Prefiller- als auch auf den Decoder-Container identisch angewendet. Es gibt kein env-var-Feld pro Rolle. Verwenden Sie für das Verhalten pro Rolle 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, nach Rang sortiert. Für Llama 70B bei TP=8 beträgt der KV-Cache jedes Tokens ungefähr 40 KB pro Rang, 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. Wenn der Puffer die Kapazität überschreitet, protokolliert der Decoder und die Clients stellen Latenzspitzen fest.
Failed to allocate memory object, retrying...Erhöhen Sie es auf 16/32 GiB oder skalierendecodingSpec.replicasSie es bei Bedarf. 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 die integrierten Funktionen von Python, um Cache-Schlüssel für Prompt-Tokens
hash()zu berechnen. Python randomisiert diesen Hash-Seed standardmäßig pro Prozess, sodass identische Eingabeaufforderungen unterschiedliche Schlüssel auf Prefiller und Decoder erzeugen und Lookups fehlschlagen. Durch das Fixieren des Seeds stimmen die Schlüssel in 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 aktiviert. 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.
Bei einem einzigen Prefill-Replikat werden alle Strategien zu diesem 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 Anzahl der Treffer im KV-Cache zu maximieren, wenn Eingabeaufforderungen gemeinsame Präfixe wie Systemaufforderungen oder Chat-Verlauf verwenden. -
Verwenden Sie bei Replikaten mit mehreren Vorbefüllungen diese Option, um die Last gleichmäßig auf die Replikate
roundrobinzu verteilen und zu vermeiden, dass ein einzelnes Prefilling-Problem auftritt.
Vollständiges Beispiel
Das folgende Manifest stellt Llama 3.3 70B auf zwei ml.p5.48xlarge-Instances (ein Prefiller, ein Decoder) bereit:
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 Ausgabe: 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 die Leitung druckt, hat der Bediener DPD nicht richtig 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 Routing-Pfade zu nutzen, und ü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 als dem Prefiller 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 über den Prefiller für die KV-Cache-Berechnung weitergeleitet und dann zur Token-Generierung an den Decoder 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
Vergewissern Sie sich 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. Wie Sie sehenRetrieved 0 out of N, hat der Decoder auf die lokale Neuberechnung zurückgegriffen — 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 KI-KI-Endpunkt aufzurufen, geben Sie endpointName Ihren InferenceEndpointConfig ein. Wenn nicht festgelegt, endpointName wird kein SageMaker AI-KI-Endpunkt erstellt und es ist nur ein direkter ALB-Aufruf verfügbar.
Beobachtbarkeit
Aktivieren Sie Metriken, indem Sie Ihre einstellenmetrics.enabled: true. InferenceEndpointConfig DPD-Metriken sind im HyperPod Inferenz-Dashboard verfügbar. Weitere Informationen finden Sie unter Implementierung von Inferenzbeobachtbarkeit 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 vorfüllen | Prefiller-only Latenz |
| Warteschlange vorfüllen | Anzahl der Anfragen, die auf das Vorbefüllen warten |
| Warteschlange dekodieren | Anzahl der Anfragen, die auf den Decoder warten |
| Zeit zum Vorfüllen | Für die Berechnung des Vorausfüllens aufgewendete Zeit |
| Latenz dekodieren | Per-token Ausgangslatenz (TPOT) |
| KV-Übertragungszeit | Zeit für die Übertragung des KV-Cache vom Prefiller zum Decoder |
| DPD-Routing zählt | Disaggregierte Anfragen im Vergleich zu Fallback-Anfragen (unter dem Schwellenwert) |
Optimieren Sie Ihren DPD-Einsatz
Die folgende Tabelle enthält eine Kurzübersicht zur Optimierung von DPD auf der Grundlage der Symptome, die Sie in Ihrem Metrik-Dashboard beobachten.
| Config | Was macht es | Standard | Wann sollte man tunen |
|---|---|---|---|
pdSpec.routingThreshold |
Mindestanzahl der Eingabe-Token, 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. Ein zu niedriger Wert erhöht den TTFT-Wert aufgrund unnötiger KV-Übertragungen bei kurzen Eingabeaufforderungen, während ein zu hoher Wert die TPOT-Verbesserung einschränkt, da weniger Anfragen den DPD-Pfad verwenden. |
pdSpec.prefillSpec.replicas |
Anzahl der Vorbefüllkapseln. | 1 |
Erhöhen Sie die Anzahl, wenn die Tiefe der Warteschlange zum Vorfüllen hoch ist, um die TTFT-Geschwindigkeit 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 von 6 während des Fluges für 70 B bei TP=8. | "8589934592"(8 GiB) |
Erhöhung, um mehr gleichzeitige KV-Übertragungen abzuwickeln. Verringern Sie den Wert, wenn Sie Speicherprobleme feststellen. Beim Erhöhen müssen Sie möglicherweise den --gpu-memory-utilization Decoder herunterfahren, um GPU-Speicher für den größeren Puffer freizugeben. |
--gpu-memory-utilization |
Ein Bruchteil des GPU-Speichers, den VllM für Gewichtungen, Aktivierungen und KV-Cache verwendet. | 0.75 |
Erhöhen Sie den Wert für mehr KV-Cache-Headroom bei langen Eingaben. Risiko: OOM vorfüllen, da beim Vorfüllen auch Speicherplatz für Aktivierungen benötigt wird. Testen Sie mit Ihrer tatsächlichen Eingabelängenverteilung. |
--max-num-seqs |
Max. Anzahl gleichzeitiger Sequenzen pro Arbeitsstapel. | 16(Vorfüller), 32 (Decoder) |
Für eine bessere Dosierung unter Last anheben. Senken Sie den Wert, wenn Sie am Vorfüller auf OOM drücken. Wird pro Rolle festgelegt über. pdSpec.{prefillSpec,decodingSpec}.args |
intelligentRoutingSpec.routingStrategy |
So wählt der Router einen Prefiller aus, 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 einzigen Prefiller oder wenn Eingabeaufforderungen gemeinsame Präfixe verwenden (Systemaufforderungen, Chat-Verlauf), um die Anzahl der Cache-Treffer zu maximieren. |
Testen Sie mit Ihrer tatsächlichen Arbeitslast und der Längenverteilung der Eingaben.
Um die Konfigurationsänderungen zu übernehmen, bearbeiten Sie Ihre Implementierungs-YAML und wenden Sie 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 Dekodierungsbereitstellung pro Endpunkt. Die Support mehrerer Dekodierungsbereitstellungen ist für eine future Version geplant.
-
Die Leistung wird bei bis zu 64 gleichzeitigen Anfragen auf ml.p5.48xlarge mit Llama 3.3 70B validiert.
-
Um von einer DPD-Bereitstellung zu einer standardmäßigen Colocation-Bereitstellung zurückzukehren, wenden Sie eine neue ohne an.
InferenceEndpointConfigpdSpec
Informationen zur Fehlerbehebung bei DPD-Bereitstellungen finden Sie unter. Probleme bei der Bereitstellung von Disaggregated Prefill and Decode (DPD)