

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Pré-preenchimento e decodificação desagregados para inferência HyperPod
<a name="sagemaker-hyperpod-model-deployment-dpd"></a>

O Disaggregated Prefill and Decode (DPD) separa as duas fases da inferência do LLM, pré-preenchimento e decodificação, em pools de GPU dedicados e transfere o cache de chave-valor (KV) entre elas pelo Elastic Fabric Adapter (EFA) usando o Remote Direct Memory Access (RDMA). GPU-Direct 

Quando o pré-preenchimento e a decodificação são executados na mesma GPU (localizada), uma única solicitação de contexto longo pode paralisar fluxos de tokens em andamento para outros clientes, aumentando a latência por token sob carga. O DPD remove essa interferência executando o pré-preenchimento vinculado à computação em um conjunto de GPUs e a decodificação limitada à largura de banda de memória em outro, produzindo uma latência mais previsível sob tráfego misto e permitindo que você escale cada fase de forma independente.

O operador de inferência gerencia a orquestração, que inclui o provisionamento do roteador, a conexão dos pods de pré-preenchimento e decodificação via LMCache e NIXL e a integração com a observabilidade. HyperPod Você pode habilitar o DPD adicionando uma `pdSpec` seção ao mesmo `InferenceEndpointConfig` recurso que você já usa para endpoints de inferência.

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

O DPD oferece o maior benefício quando todas as seguintes condições estão presentes:
+ **Modelos grandes e densos** — 70B\+ parâmetros (por exemplo, Llama 3.3 70B).
+ **Entradas longas** — mais de 4.000 tokens de entrada. Inter-token a melhoria da latência (ITL) aumenta com o comprimento da entrada, pois preenchidos mais longos causam mais interferência de decodificação quando colocados.
+ **Simultaneidade sustentada** — mais de 2 solicitações por segundo. Sem solicitações simultâneas competindo pela mesma GPU, não há nada para desagregar.
+ **Saídas moderadas ou longas** — mais de 256 tokens de saída. Mais tokens de saída significam mais benefícios cumulativos da latência estável por token.

Se sua carga de trabalho tem entradas curtas, baixa simultaneidade ou usa modelos pequenos, uma implantação colocalizada padrão é mais simples e tem um bom desempenho.

## Pré-requisitos
<a name="sagemaker-hyperpod-model-deployment-dpd-prereqs"></a>

Antes de implantar endpoints de inferência que usam pré-preenchimento e decodificação desagregados, você precisa configurar os seguintes componentes em seu ambiente de desenvolvimento local:
+ [AWS Interface de linha de comando (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)
+ Acesso ao seu cluster HyperPod Amazon EKS via [kubectl](https://kubernetes.io/docs/tasks/tools/)
+ Token [Hugging Face](https://huggingface.co/) que permite acesso de leitura ao respectivo ponto de verificação do modelo. Isso não é necessário se o ponto de verificação do modelo já estiver localizado em um bucket do Amazon S3.
+ Uma imagem de trabalho que inclui vLLM, LMCache, NVIDIA NIXL e o provedor EFA libfabric. As seguintes opções de imagem são suportadas:
  + DLC: `public.ecr.aws/deep-learning-containers/vllm:server-hyperpod-cuda-v1.1`
  + LMCache: `lmcache/vllm-openai:v0.4.3`

  Ambas as imagens incluem LMCache 0.4.3, vLLM 0.19.0 e NIXL 1.0.0.
+ HyperPod Operador de inferência **versão 3.2 ou posterior** instalado. O DPD não é suportado em versões anteriores. O operador é instalado por padrão nos clusters recém-criados do HyperPod Amazon EKS. Se você pretende usar um cluster existente, siga as instruções de instalação em[Configurando seus HyperPod clusters para implantação de modelos](sagemaker-hyperpod-model-deployment-setup.md). Verifique sua versão:

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

**Importante**  
O pré-preenchimento e a decodificação desagregados exigem EFA-capable instâncias com suporte a RDMA. GPU-Direct Os seguintes tipos de instância são compatíveis:`ml.p5.48xlarge`,`ml.p5e.48xlarge`,`ml.p5en.48xlarge`,`ml.p6-b200.48xlarge`,`ml.p6-b300.48xlarge`. Outros tipos de instância não são compatíveis com o DPD.

## Implemente um endpoint de DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-deploy"></a>

A maioria dos `InferenceEndpointConfig` campos é compartilhada com endpoints não DPD e documentada em. [Implantar modelos de base e modelos personalizados e ajustados](sagemaker-hyperpod-model-deployment-deploy.md) Para habilitar o DPD, adicione as seções a seguir ao seu manifesto.

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

Declara a prefill/decode topologia e especifica os argumentos. A presença desse campo é o que torna o endpoint desagregado: o operador cria implantações separadas para pré-preenchimento e decodificação e as conecta por meio do roteador e do back-end 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`  
Dimensione, pré-preencha e decodifique de forma independente.

`resources`  
Aplicado à especificação do pod da função. Top-level`worker.resources`é ignorado para pods de DPD; os valores por função são substituídos.

`routingThreshold`  
Limite de comprimento do token que encaminha as solicitações para o caminho desagregado. As solicitações que não atendem a esse limite ignoram o pré-preenchedor e vão diretamente para o decodificador.

`args`  
Sinalizadores vLLM específicos para essa função. Mesclado `worker.args` na inicialização: os sinalizadores já inseridos `worker.args` são substituídos pelo valor por função; os sinalizadores que não estão presentes são anexados.

### `Variáveis de ambiente do DPD: Variáveis de ambiente`
<a name="sagemaker-hyperpod-model-deployment-dpd-fields-env"></a>

Essas variáveis de ambiente são aplicadas de forma idêntica aos contêineres do pré-preenchedor e do decodificador; não há campo env-var por função. Para comportamento por função, use `pdSpec.{prefillSpec,decodingSpec}.args` em vez disso.

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

`PD_BUFFER_SIZE`(8 GiB)  
Buffer de GPU reservado no decodificador para transferências de cache de entrada em KV, dimensionado por classificação. Para o Llama 70B com TP=8, o cache KV de cada token é de aproximadamente 40 KB por classificação, portanto, um prompt de 6.000 tokens ocupa aproximadamente 0,23 GB por classificação e 8 GiB contém aproximadamente 35 dessas transferências em voo. Quando o buffer excede a capacidade, os registros do decodificador `Failed to allocate memory object, retrying...` e os clientes veem picos de latência. Aumente para 16/32 GiB ou escale, `decodingSpec.replicas` se necessário.

`LMCACHE_SAVE_DECODE_CACHE`: `"False"`  
Desativa o cache L1 redundante no decodificador. O pré-preenchedor é a fonte confiável dos acessos ao cache.

`PYTHONHASHSEED`: `"0"`  
O LMCache usa o Python integrado `hash()` para calcular as chaves de cache do token de prompt. O Python randomiza essa semente de hash por processo por padrão, então prompts idênticos produzem chaves diferentes no pré-preenchedor e no decodificador, e as pesquisas falham. Fixar a semente faz com que as chaves concordem entre os frutos.

### Configurar a estratégia de roteamento
<a name="sagemaker-hyperpod-model-deployment-dpd-fields-routing"></a>

A `intelligentRoutingSpec` seção define a estratégia de roteamento que o roteador DPD usa para selecionar um pré-preenchedor para cada solicitação. O roteador é criado automaticamente quando `pdSpec` está presente; esta seção é opcional e o padrão é. `prefixaware`

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

O DPD também pode ser integrado com roteamento inteligente e cache KV. Para obter mais informações, consulte [Configure o cache KV e o roteamento inteligente](sagemaker-hyperpod-model-deployment-caching-routing.md#sagemaker-hyperpod-model-deployment-deploy-ftm-cache-route).

Com uma única réplica pré-preenchida, todas as estratégias são direcionadas para essa réplica. A escolha só afeta o comportamento quando`prefillSpec.replicas > 1`:
+ Para uma única réplica pré-preenchida, use `prefixaware` (o padrão) para maximizar os acessos ao cache KV quando as solicitações compartilham prefixos comuns, como solicitações do sistema ou histórico de bate-papo.
+ Para várias réplicas de pré-preenchimento, use `roundrobin` para distribuir a carga uniformemente entre as réplicas e evitar a interferência de um único pré-preenchedor.

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

O manifesto a seguir implanta o Llama 3.3 70B em duas instâncias ml.p5.48xlarge (um pré-preenchedor, um decodificador):

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

Aplique o manifesto:

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

## Verificar a implantação
<a name="sagemaker-hyperpod-model-deployment-dpd-verify"></a>

A extração da imagem e o carregamento do modelo demoram vários minutos. Monitore o status do pod:

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

Uma implantação saudável mostra:

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

Cada pod de modelo tem 3 contêineres (trabalhador vLLM, proxy reverso Nginx, coletor). OpenTelemetry O pod do roteador tem 2 contêineres (roteador, OpenTelemetry coletor). Verifique o `InferenceEndpointConfig` status:

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

Saída esperada: `DPD prefill and decode deployments are ready`

### Verifique as funções do DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-verify-roles"></a>

Confirme os relatórios do pré-preenchedor `sender` e os relatórios do decodificador. `receiver` Esse é o sinal de inicialização mais exigente: se os dois pods relatarem a mesma função ou nenhum imprimir a linha, o operador não conectou o DPD corretamente.

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

Saída esperada:

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

## Invocar o endpoint
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke"></a>

Quando o endpoint estiver pronto, envie um prompt curto e um longo para exercitar os dois caminhos de roteamento e, em seguida, verifique os registros para confirmar a transferência de KV pelo 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
```

### Aviso curto (abaixo do limite, direto para o decodificador)
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-short"></a>

Solicitações com menos tokens do que `routingThreshold` ignoram o pré-preenchedor e vão diretamente para o decodificador:

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

### Solicitação longa (excede o limite, caminho DPD)
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-long"></a>

Solicitações que excedem o limite são roteadas pelo pré-preenchedor para computação de cache KV e, em seguida, para o decodificador para geração de 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}"
'
```

### Verifique a transferência de KV
<a name="sagemaker-hyperpod-model-deployment-dpd-invoke-verify-kv"></a>

Depois de enviar um aviso longo, confirme se o cache KV foi transferido verificando os registros do decodificador:

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

Saída esperada (uma linha por classificação 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`com N > 0 confirma que o cache KV cruzou o canal NIXL com sucesso. Se você ver`Retrieved 0 out of N`, o decodificador voltou para o recálculo local — veja. [Problemas de implantação de pré-preenchimento e decodificação desagregados (DPD)](sagemaker-hyperpod-model-deployment-ts-dpd.md)

Você também pode verificar a decisão de roteamento nos registros do roteador:

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

Para o aviso longo, você deve ver:

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

Para o breve aviso:

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

**nota**  
Para invocar por meio de um endpoint de IA SageMaker AI, `endpointName` defina seu. `InferenceEndpointConfig` Se não `endpointName` estiver definido, nenhum endpoint SageMaker AI AI será criado e somente a invocação direta do ALB estará disponível.

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

Ative as métricas `metrics.enabled: true` configurando seu`InferenceEndpointConfig`. As métricas do DPD estão disponíveis no painel de HyperPod inferência. Para obter mais informações, consulte [Implementando a observabilidade de inferência em clusters HyperPod](sagemaker-hyperpod-model-deployment-observability.md).

As seguintes DPD-specific métricas estão disponíveis:


**DPD-specific métricas**  

| Métrica | Description | 
| --- | --- | 
| E2E TTFT | Tempo total até o primeiro token (pré-preenchimento\+transferência de KV \+roteamento) | 
| Preencha previamente o TTFT | Prefiller-only latência | 
| Fila de pré-preenchimento | Número de solicitações aguardando o pré-preenchimento | 
| Fila de decodificação | Número de solicitações aguardando no decodificador | 
| Tempo de pré-preenchimento | Tempo gasto no cálculo do pré-preenchimento | 
| Latência de decodificação | Per-token latência de saída (TPOT) | 
| Tempo de transferência de KV | Hora de transferir o cache de KV do pré-preenchedor para o decodificador | 
| Contagens de roteamento DPD | Solicitações desagregadas versus solicitações alternativas (abaixo do limite) | 

## Ajuste sua implantação de DPD
<a name="sagemaker-hyperpod-model-deployment-dpd-tuning"></a>

A tabela a seguir fornece uma referência rápida para ajustar o DPD com base nos sintomas que você observa em seu painel de métricas.


**Referência de ajuste do DPD**  

| Config | O que ela faz | Padrão | Quando sintonizar | 
| --- | --- | --- | --- | 
| pdSpec.routingThreshold | Tokens de entrada mínimos a serem roteados pelo pré-preenchedor. Solicitações abaixo desse limite vão diretamente para o decodificador. | 4096 | O padrão funciona bem para a maioria das cargas de trabalho. Configurá-lo como muito baixo aumenta o TTFT devido a transferências desnecessárias de KV em prompts curtos, enquanto configurá-lo como muito alto limita a melhoria do TPOT, pois menos solicitações seguem o caminho do DPD. | 
| pdSpec.prefillSpec.replicas | Número de cápsulas de pré-enchimento. | 1 | Aumente a escala se a profundidade da fila de pré-preenchimento for alta para melhorar o TTFT de pré-preenchimento. | 
| PD\_BUFFER\_SIZE | Buffer de GPU do decodificador para transferências de KV recebidas (por classificação). 8 GiB contém aproximadamente 35 K-token transferências em voo (6) para 70 B a TP=8. | "8589934592"(8 GiB) | Aumente para lidar com mais transferências simultâneas de KV. Diminua se você tiver problemas de memória. Ao aumentar, talvez seja necessário diminuir --gpu-memory-utilization o decodificador para liberar memória da GPU para o buffer maior. | 
| --gpu-memory-utilization | Fração da memória da GPU que o vLLM usa para pesos, ativações e cache de KV. | 0.75 | Aumente para obter mais espaço livre de cache em KV em entradas longas. Risco: OOM do pré-preenchedor porque o pré-preenchimento também precisa de memória para ativações. Teste com sua distribuição real do comprimento de entrada. | 
| --max-num-seqs | Máximo de sequências simultâneas por lote de trabalho. | 16(pré-preenchedor), 32 (decodificador) | Levante para uma melhor dosagem sob carga. Abaixe se atingir OOM no pré-preenchedor. Defina por função viapdSpec.{prefillSpec,decodingSpec}.args. | 
| intelligentRoutingSpec.routingStrategy | Como o roteador seleciona um pré-preenchedor quando existem várias réplicas. | prefixaware | Use roundrobin para distribuir uniformemente a carga em várias réplicas de pré-preenchimento. Use prefixaware ou kvaware com um único pré-preenchedor ou quando as solicitações compartilharem prefixos comuns (solicitações do sistema, histórico de bate-papo) para maximizar os acessos ao cache. | 

Teste com sua carga de trabalho real e a distribuição do comprimento de entrada.

Para aplicar as alterações de configuração, edite seu YAML de implantação e reaplique:

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

## Limitações conhecidas
<a name="sagemaker-hyperpod-model-deployment-dpd-limitations"></a>
+ O DPD é recomendado para modelos densos com 70B ou mais parâmetros. Modelos e Mixture-of-Experts modelos menores normalmente não se beneficiam da desagregação.
+ A versão atual oferece suporte a uma única implantação de decodificação por endpoint. O suporte para várias implantações de decodificação está planejado para uma versão futura.
+ O desempenho é validado em até 64 solicitações simultâneas no ml.p5.48xlarge com o Llama 3.3 70B.
+ Para reverter de uma implantação de DPD para uma implantação colocalizada padrão, aplique uma nova sem. `InferenceEndpointConfig` `pdSpec`

Para solucionar problemas de implantações de DPD, consulte. [Problemas de implantação de pré-preenchimento e decodificação desagregados (DPD)](sagemaker-hyperpod-model-deployment-ts-dpd.md)