

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Precompilazione e decodifica disaggregate per l'inferenza HyperPod
<a name="sagemaker-hyperpod-model-deployment-dpd"></a>

Disaggregated Prefill and Decode (DPD) separa le due fasi di inferenza LLM, prefill e decodifica, su pool di GPU dedicati e trasferisce la cache chiave-valore (KV) tra di loro tramite Elastic Fabric Adapter (EFA) utilizzando Remote Direct Memory Access (RDMA). GPU-Direct 

Quando la precompilazione e la decodifica vengono eseguite sulla stessa GPU (in co-location), una singola richiesta a lungo contesto può bloccare i flussi di token in corso per altri client, aumentando la latenza per token sotto carico. DPD rimuove questa interferenza eseguendo la precompilazione associata al calcolo su un set di GPU e la decodifica limitata alla larghezza di banda di memoria su un altro, producendo una latenza più prevedibile in caso di traffico misto e consentendo di scalare ogni fase in modo indipendente.

L'operatore di inferenza gestisce l'orchestrazione, che include il provisioning del router, il cablaggio dei pod di precompilazione e decodifica tramite LMCache e NIXL e l'integrazione con l'osservabilità. HyperPod Puoi abilitare DPD aggiungendo una sezione alla stessa risorsa che già utilizzi per gli endpoint di inferenza. `pdSpec` `InferenceEndpointConfig`

## Quando DPD aiuta
<a name="sagemaker-hyperpod-model-deployment-dpd-when"></a>

DPD offre il massimo vantaggio quando sono presenti tutte le seguenti condizioni:
+ **Modelli ad alta densità**: parametri 70B\+ (ad esempio, Llama 3.3 70B).
+ Ingressi **lunghi: oltre 4.000 token di input**. Inter-token Il miglioramento della latenza (ITL) varia in base alla lunghezza dell'input, poiché i preriempimenti più lunghi causano maggiori interferenze di decodifica quando vengono collocati in modo codificato.
+ **Concorrenza** sostenuta: più di 2 richieste al secondo. Senza richieste simultanee in competizione per la stessa GPU, non c'è nulla da disaggregare.
+ Uscite **moderate o lunghe: oltre 256 token di output**. Più token di output significano maggiori vantaggi cumulativi derivanti da una latenza stabile per token.

Se il carico di lavoro prevede input brevi, bassa concorrenza o utilizza modelli di piccole dimensioni, un'implementazione standard in colocation è più semplice e offre buone prestazioni.

## Prerequisiti
<a name="sagemaker-hyperpod-model-deployment-dpd-prereqs"></a>

Prima di distribuire endpoint di inferenza che utilizzano Disaggregated Prefill and Decode, è necessario configurare i seguenti componenti nell'ambiente di sviluppo locale:
+ [AWS Interfaccia a riga di comando (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)
+ Accesso al tuo cluster HyperPod Amazon EKS tramite [kubectl](https://kubernetes.io/docs/tasks/tools/)
+ Token [Hugging Face](https://huggingface.co/) che consente l'accesso in lettura al rispettivo checkpoint del modello. Questo non è necessario se il checkpoint del modello si trova già in un bucket Amazon S3.
+ Un'immagine di lavoro che include VLLm, LMCache, NVIDIA NIXL e il provider EFA libfabric. Sono supportate le seguenti opzioni di immagine:
  + DLC: `public.ecr.aws/deep-learning-containers/vllm:server-hyperpod-cuda-v1.1`
  + Cache LM: `lmcache/vllm-openai:v0.4.3`

  Entrambe le immagini includono LMCache 0.4.3, VLLm 0.19.0 e NIXL 1.0.0.
+ HyperPod È installata **la versione 3.2 o successiva di Inference** Operator. DPD non è supportato nelle versioni precedenti. L'operatore viene installato per impostazione predefinita nei cluster HyperPod Amazon EKS appena creati. Se intendi utilizzare un cluster esistente, segui le istruzioni di installazione riportate in[Configurazione dei HyperPod cluster per l'implementazione dei modelli](sagemaker-hyperpod-model-deployment-setup.md). Verifica la tua versione:

  ```
  kubectl get deployment hyperpod-inference-operator-controller-manager \
    -n hyperpod-inference-system \
    -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].image}{"\n"}'
  ```

**Importante**  
La precompilazione e la decodifica disaggregate richiedono EFA-capable istanze con supporto RDMA. GPU-Direct Sono supportati i seguenti tipi di istanza:,,,,. `ml.p5.48xlarge` `ml.p5e.48xlarge` `ml.p5en.48xlarge` `ml.p6-b200.48xlarge` `ml.p6-b300.48xlarge` Altri tipi di istanza non sono supportati per DPD.

## Implementate un endpoint DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-deploy"></a>

La maggior parte dei `InferenceEndpointConfig` campi è condivisa con endpoint non DPD e documentata in. [Implementazione di modelli di fondazione e di modelli ottimizzati con fine-tuning personalizzati](sagemaker-hyperpod-model-deployment-deploy.md) Per abilitare DPD, aggiungete le seguenti sezioni al manifesto.

### Prefill-Decode `Specifiche: PDSpec`
<a name="sagemaker-hyperpod-model-deployment-dpd-fields-pdspec"></a>

Dichiara la topologia e specifica gli prefill/decode argomenti. La presenza di questo campo è ciò che rende l'endpoint disaggregato: l'operatore crea implementazioni separate per la precompilazione e la decodifica e le collega tra loro tramite il router e il backend LMCache PD.

```
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`  
Scalabilità, precompilazione e decodifica in modo indipendente.

`resources`  
Applicato alle specifiche del pod del ruolo. Top-level`worker.resources`viene ignorato per i pod DPD; i valori per ruolo hanno la precedenza.

`routingThreshold`  
Soglia di lunghezza del token che indirizza le richieste verso il percorso disaggregato. Le richieste che non soddisfano questa soglia ignorano il prefiller e vanno direttamente al decoder.

`args`  
Bandiere VLM specifiche per quel ruolo. Uniti `worker.args` all'avvio: i flag già presenti `worker.args` vengono sostituiti con il valore per ruolo; i flag non presenti vengono aggiunti.

### Variabili di ambiente DPD`:` variabili d'ambiente
<a name="sagemaker-hyperpod-model-deployment-dpd-fields-env"></a>

Queste variabili di ambiente vengono applicate in modo identico sia al contenitore del prefiller che al contenitore del decoder; non esiste un campo env-var per ruolo. Per `pdSpec.{prefillSpec,decodingSpec}.args` un comportamento per ruolo, usa invece.

```
environmentVariables:
  - name: PD_BUFFER_SIZE
    value: "8589934592"
  - name: LMCACHE_SAVE_DECODE_CACHE
    value: "False"
  - name: PYTHONHASHSEED
    value: "0"
```

`PD_BUFFER_SIZE`(8 GiB)  
Buffer GPU riservato al decoder per i trasferimenti di cache KV in entrata, dimensionato per rank. Per Llama 70B a TP=8, la cache KV di ogni token è di circa 40 KB per rank, quindi un prompt da 6000 token occupa circa 0,23 GB per rank e 8 GiB contiene circa 35 trasferimenti in volo di questo tipo. Quando il buffer supera la capacità, il decoder si registra e i client registrano picchi di latenza. `Failed to allocate memory object, retrying...` Aumenta a 16/32 GiB o scala `decodingSpec.replicas` se necessario.

`LMCACHE_SAVE_DECODE_CACHE`: `"False"`  
Disattiva la memorizzazione nella cache L1 ridondante sul decoder. Il prefiller è la fonte di verità per gli accessi alla cache.

`PYTHONHASHSEED`: `"0"`  
LMCache utilizza la funzionalità integrata di Python per calcolare le chiavi della cache `hash()` prompt-token. Python randomizza l'hash seed per processo per impostazione predefinita, quindi prompt identici producono chiavi diverse su prefiller e decoder e le ricerche non vengono eseguite. Se si fissa il seme, le chiavi si accordano tra i baccelli.

### Configura la strategia di routing
<a name="sagemaker-hyperpod-model-deployment-dpd-fields-routing"></a>

La `intelligentRoutingSpec` sezione imposta la strategia di routing utilizzata dal router DPD per selezionare un prefiller per ogni richiesta. Il router viene creato automaticamente quando è presente; questa sezione `pdSpec` è facoltativa e l'impostazione predefinita è. `prefixaware`

```
intelligentRoutingSpec:
  enabled: true
  routingStrategy: prefixaware
```

DPD può anche essere integrato con il routing intelligente e la memorizzazione nella cache KV. Per ulteriori informazioni, consulta [Configura la memorizzazione nella cache KV e il routing intelligente](sagemaker-hyperpod-model-deployment-caching-routing.md#sagemaker-hyperpod-model-deployment-deploy-ftm-cache-route).

Con un'unica replica di precompilazione, tutte le strategie vengono indirizzate verso quella replica. La scelta influisce sul comportamento solo quando: `prefillSpec.replicas > 1`
+ Per una singola replica di precompilazione, utilizza `prefixaware` (impostazione predefinita) per massimizzare gli accessi alla cache KV quando i prompt condividono prefissi comuni come i prompt di sistema o la cronologia chat.
+ Per più repliche di precompilazione, utilizzatela per distribuire il carico in modo uniforme tra le repliche ed evitare l'individuazione di un singolo `roundrobin` prefiller.

### Esempio completo
<a name="sagemaker-hyperpod-model-deployment-dpd-deploy-example"></a>

Il seguente manifesto distribuisce Llama 3.3 70B su due istanze ml.p5.48xlarge (un prefiller, un 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"
```

Applica il manifesto:

```
kubectl apply -f inference_endpoint_dpd_config.yaml
```

## Verifica della distribuzione
<a name="sagemaker-hyperpod-model-deployment-dpd-verify"></a>

L'estrazione dell'immagine e il caricamento del modello richiedono alcuni minuti. Monitora lo stato del pod:

```
kubectl get pods -A \
  | grep -E "prefill-|decode-|router"
```

Una corretta implementazione dimostra:

```
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
```

Ogni pod modello ha 3 contenitori (vLLM worker, Nginx reverse proxy, collector). OpenTelemetry Il pod del router ha 2 contenitori (router, collector). OpenTelemetry Controlla lo `InferenceEndpointConfig` stato:

```
kubectl get inferenceendpointconfig dpd-test -n default \
  -o jsonpath='{.status.conditions[0].message}{"\n"}'
```

Output previsto: `DPD prefill and decode deployments are ready`

### Verifica i ruoli DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-verify-roles"></a>

Conferma i rapporti del precompilatore `sender` e dei decodificatori. `receiver` Questo è il segnale di avvio più importante: se entrambi i pod riportano lo stesso ruolo o nessuno dei due riporta la linea, l'operatore non ha cablato DPD correttamente.

```
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
```

Output previsto:

```
'pd_role': 'sender'
'pd_role': 'receiver'
```

## Richiamare l'endpoint
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke"></a>

Una volta che l'endpoint è pronto, invia un prompt breve e uno lungo per eseguire entrambi i percorsi di routing, quindi controlla i log per confermare il trasferimento KV tramite EFA.

```
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
```

### Richiesta breve (sotto la soglia, diretta al decoder)
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-short"></a>

Le richieste con un numero di token inferiore a quello di `routingThreshold` bypassano il prefiller e vanno direttamente al 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
    }'
```

### Richiesta lunga (supera la soglia, percorso DPD)
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-long"></a>

Le richieste che superano la soglia vengono inoltrate attraverso il prefiller per il calcolo della cache KV, quindi verso il decoder per la generazione di token:

```
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}"
'
```

### Verifica il trasferimento KV
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-verify-kv"></a>

Dopo aver inviato una richiesta lunga, conferma che la cache KV è stata trasferita controllando i registri del decoder:

```
kubectl logs $DECODE_POD -n ${NAMESPACE} -c decode-${DEPLOYMENT_NAME} \
  | grep -E "Retrieved.*tokens.*throughput" | tail -2
```

Output previsto (una riga per grado TP):

```
[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 tokens`con N > 0 conferma che la cache KV ha attraversato correttamente il canale NIXL. Se vedi`Retrieved 0 out of N`, il decoder è tornato alla ricalcolo locale: vedi. [Problemi di implementazione di Disaggregated Prefill and Decode (DPD)](sagemaker-hyperpod-model-deployment-ts-dpd.md)

Puoi anche verificare la decisione di routing nei log del router:

```
kubectl logs $ROUTER_POD -n hyperpod-inference-system -c router-container --tail=20 \
  | grep -E "Conditional routing"
```

Per il prompt lungo, dovresti vedere:

```
[INFO] Conditional routing: estimated_tokens=6750, threshold=4096, disaggregate=True
```

Per il prompt breve:

```
[INFO] Conditional routing: estimated_tokens=12, threshold=4096, disaggregate=False
```

**Nota**  
Per richiamare tramite un endpoint SageMaker AI, imposta `endpointName` il tuo. `InferenceEndpointConfig` Se non `endpointName` è impostato, non viene creato alcun endpoint SageMaker AI AI ed è disponibile solo la chiamata ALB diretta.

## Osservabilità
<a name="sagemaker-hyperpod-model-deployment-dpd-observability"></a>

Abilita le metriche impostando il tuo. `metrics.enabled: true` `InferenceEndpointConfig` Le metriche DPD sono disponibili nella dashboard di inferenza. HyperPod Per ulteriori informazioni, consulta [Implementazione dell'osservabilità inferenziale sui cluster HyperPod](sagemaker-hyperpod-model-deployment-observability.md).

Sono disponibili le seguenti DPD-specific metriche:


**DPD-specific metriche**  

| Metrica | Description | 
| --- | --- | 
| E2E TTFT | Tempo complessivo necessario alla creazione del primo token (precompilazione, trasferimento KV, routing) | 
| Precompila TTFT | Prefiller-only latenza | 
| Coda di precompilazione | Numero di richieste in attesa di precompilazione | 
| Coda di decodifica | Numero di richieste in attesa sul decoder | 
| Tempo di precompilazione | Tempo impiegato per il calcolo della precompilazione | 
| Latenza di decodifica | Per-token latenza di uscita (TPOT) | 
| Tempo di trasferimento KV | È ora di trasferire la cache KV dal prefiller al decoder | 
| Il routing DPD conta | Richieste disaggregate e richieste di fallback (al di sotto della soglia) | 

## Ottimizzate la distribuzione di DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-tuning"></a>

La tabella seguente fornisce un riferimento rapido per ottimizzare DPD in base ai sintomi osservati nella dashboard delle metriche.


**Riferimento per l'ottimizzazione DPD**  

| Config | Cosa fa | Predefinita | Quando sintonizzarsi | 
| --- | --- | --- | --- | 
| pdSpec.routingThreshold | Token di input minimi da instradare attraverso il prefiller. Le richieste al di sotto di questa soglia vengono inviate direttamente al decoder. | 4096 | L'impostazione predefinita funziona bene per la maggior parte dei carichi di lavoro. Impostarlo su un valore troppo basso aumenta il TTFT a causa di trasferimenti KV non necessari su prompt brevi, mentre impostarlo su un valore troppo alto limita il miglioramento del TPOT perché il percorso DPD è composto da un minor numero di richieste. | 
| pdSpec.prefillSpec.replicas | Numero di pod di preriempimento. | 1 | Aumenta se la profondità della coda di precompilazione è elevata per migliorare il TTFT di precompilazione. | 
| PD\_BUFFER\_SIZE | Buffer GPU di decodifica per trasferimenti KV in entrata (per rank). 8 GiB detiene circa 35 K-token trasferimenti in volo 6 per 70 B a TP=8. | "8589934592"(8 GiB) | Aumenta per gestire più trasferimenti KV simultanei. Riduci se riscontri problemi di memoria. Quando si aumenta, potrebbe essere necessario --gpu-memory-utilization abbassare il livello del decoder per liberare memoria della GPU per un buffer più grande. | 
| --gpu-memory-utilization | Frazione della memoria GPU utilizzata da VLLm per pesi, attivazioni e cache KV. | 0.75 | Aumentalo per avere più spazio nella cache KV su ingressi lunghi. Rischio: prefiller OOM perché il prefill necessita anche di memoria per le attivazioni. Esegui il test con la distribuzione effettiva della lunghezza in ingresso. | 
| --max-num-seqs | Numero massimo di sequenze simultanee per batch di lavoro. | 16(precompilatore), (decodificatore) 32 | Aumenta per una migliore dosatura sotto carico. Si accende premendo OK sul prefiller. Imposta per ruolo tramite. pdSpec.{prefillSpec,decodingSpec}.args | 
| intelligentRoutingSpec.routingStrategy | In che modo il router seleziona un prefiller quando esistono più repliche. | prefixaware | Utilizzato roundrobin per distribuire uniformemente il carico su più repliche di prefiller. Utilizzalo prefixaware o kvaware con un singolo prefiller o quando i prompt condividono prefissi comuni (istruzioni di sistema, cronologia chat) per massimizzare gli accessi alla cache. | 

Esegui il test con il carico di lavoro effettivo e la distribuzione della lunghezza di input.

Per applicare le modifiche alla configurazione, modifica il codice YAML della tua implementazione e riapplica:

```
kubectl apply -f inference_endpoint_dpd_config.yaml
```

## Limiti noti
<a name="sagemaker-hyperpod-model-deployment-dpd-limitations"></a>
+ DPD è consigliato per modelli ad alta densità con 70 B o più parametri. I modelli e Mixture-of-Experts i modelli più piccoli in genere non traggono vantaggio dalla disaggregazione.
+ La versione corrente supporta una singola implementazione di decodifica per endpoint. Il supporto per più implementazioni di decodifica è previsto per le future release.
+ Le prestazioni sono convalidate fino a 64 richieste simultanee su ml.p5.48xlarge con Llama 3.3 70B.
+ Per passare da una distribuzione DPD a una distribuzione standard in colocation, applicane una nuova senza. `InferenceEndpointConfig` `pdSpec`

Per la risoluzione dei problemi relativi alle implementazioni DPD, consulta. [Problemi di implementazione di Disaggregated Prefill and Decode (DPD)](sagemaker-hyperpod-model-deployment-ts-dpd.md)