One Long Prompt Shouldn't Freeze Everyone's Tokens: Prefill/Decode Disaggregation

Iniciado por joomlamz, Hoje at 18:25

Respostas: 1   |   Visualizações: 2

Tópico anterior - Tópico seguinte

0 Membros e 1 Visitante estão a ver este tópico.

Saudações, pessoal do webmastersmz.com! Como especialista em tecnologia, analisei com atenção o tópico "One Long Prompt Shouldn't Freeze Everyone's Tokens: Prefill/Decode Disaggregation". Este é um tema super relevante, especialmente com o boom dos Modelos de Linguagem Grandes (LLMs) e a inferência de IA. Baza fixe!

No fundo, o problema que se levanta é o seguinte: quando estamos a interagir com um LLM e enviamos um 'prompt' muito longo – tipo uma instrução super detalhada ou um texto extenso para análise – a fase inicial de processamento desse prompt, conhecida como 'prefill' (ou pré-preenchimento/inferência de entrada), consome imensos recursos da GPU. Durante esta fase, que pode demorar um bocado para prompts extensos, a GPU fica 'congelada' ou totalmente ocupada com *aquele* prompt específico. Isso significa que outros utilizadores ou outros pedidos mais curtos ficam à espera, paralisados, sem conseguir gerar novos tokens ('decode'). É como se um único cliente no restaurante estivesse a monopolizar a cozinha inteira só para preparar o seu mega-pedido!

A solução proposta é a "Disaggregation" (desagregação ou separação) do Prefill e do Decode. Basicamente, consiste em tratar estas duas fases de forma distinta e, se possível, em paralelo. Em vez de uma única GPU ou um único processo a fazer tudo em sequência, podemos ter:

1.  **Recursos Dedicados para Prefill:** Por exemplo, usar uma parte da GPU ou até mesmo GPUs separadas (ou recursos de CPU, dependendo da arquitetura) para lidar com o pré-processamento dos prompts longos.
2.  **Recursos Dedicados para Decode:** Ao mesmo tempo, outros recursos podem estar a lidar com a geração de tokens (decode) para outros prompts, sejam eles novos ou que já passaram pela fase de prefill.

Esta separação permite que a inferência do LLM seja muito mais eficiente. A fase de pré-preenchimento de um prompt grande não 'bloqueia' a geração de respostas para outros prompts. É como ter um 'chef de preparação' e um 'chef de cozinha' a trabalhar lado a lado, mas em tarefas diferentes.

Os benefícios são imediatos e cruciais para a escalabilidade de serviços baseados em IA:

*   **Maior Débito (Throughput):** Mais prompts podem ser processados por unidade de tempo, servindo mais utilizadores simultaneamente.
*   **Menor Latência:** Os tempos de resposta diminuem, especialmente para prompts mais curtos, que não precisam de esperar que um prompt longo termine o seu prefill.
*   **Melhor Utilização da GPU:** A placa gráfica é usada de forma mais eficaz, sem períodos de 'ociosidade' desnecessária enquanto espera por uma fase específica.
*   **Experiência do Utilizador Aprimorada:** Interações mais fluidas e rápidas com sistemas de IA.

Este é um avanço técnico significativo que tem implicações diretas para qualquer um de nós que esteja a desenvolver ou a gerir plataformas que usam LLMs, desde chatbots avançados a ferramentas de geração de conteúdo. Quero mesmo ouvir a vossa opinião sobre isto!

Acham que esta abordagem vai ser o novo padrão? Quais são os desafios na implementação desta desagregação em ambientes de produção? Já tiveram experiências onde prompts longos 'congelaram' os vossos sistemas? Vamos debater sobre estas e outras questões no nosso fórum webmastersmz.com! A vossa perspectiva é valiosa, pá!

Para garantir que os vossos projetos e fóruns rodam sem falhas, convido-vos a conhecer as soluções de alojamento de alta performance da AplicHost em https://aplichost.com.

One Long Prompt Shouldn't Freeze Everyone's Tokens: Prefill/Decode Disaggregation



Tópico: One Long Prompt Shouldn't Freeze Everyone's Tokens: Prefill/Decode Disaggregation
Categoria: Tutoriais | Programação & Tecnologia
Idioma Principal: Português (Conteúdo de Tecnologia)

Descrição do Conteúdo / Informações:
-------------------------------------------------------------------------
An LLM request is two workloads in a trench coat — a heavy, bursty prefill and a stream of tiny latency-sensitive decodes. Running them on the same engines lets one big prompt stall everyone. Splitting them fixes it.

TL;DR: Every LLM request is two very different jobs. Prefill reads the whole prompt — heavy, bursty, and slow for long contexts. Decode then emits tokens one at a time — tiny, but latency-sensitive. Run them on the same engines and a big prefill jumps ahead of everyone's decodes: head-of-line blocking, and the token stream stutters. Prefill/decode disaggregation puts prefill and decode on separate pools so decodes never queue behind a prefill. In a runnable Go simulation, splitting the pools cut p99 inter-token latency by 66% (88ms → 30ms) — trading a little time-to-first-token for a far smoother stream. This is now standard practice in frontier serving stacks (DistServe, Splitwise, vLLM × Mooncake).

Mental model: a coffee shop with one worker who both grinds beans and pours espresso. A customer orders a giant batch grind and everyone waiting for a simple pour is stuck behind it. Split the shop into a grinder station and a pour station and the pours keep flowing no matter how big the grind.



The problem: two workloads, one queue


Serving an LLM token is not one kind of work — it's two:


Prefill processes the entire prompt to build the KV cache. It's a big, compute-bound burst, and it scales with prompt length: a 100k-token context is a genuinely slow operation.


Decode generates the response one token at a time, each step cheap but on the critical path of what the user feels — the inter-token latency (ITL) is the smoothness of the stream.

Colocate them — the default — and they fight for the same compute. Continuous batching helps throughput but doesn't remove the conflict: when the engine runs a long prefill, the decodes it's also hosting have to wait. And they can't flee to a less-busy engine, because this engine holds their KV cache. So one long-context prompt lands and every active token stream on that engine stutters. Your p99 ITL is hostage to your longest prompt.



The pattern: split the pools


Disaggregation (DistServe, Splitwise) separates the two phases onto different hardware:

• A prefill pool does nothing but build KV caches — bursty, compute-heavy work, isolated.

• A decode pool does nothing but stream tokens — steady, latency-sensitive work, isolated.

• The KV cache is handed off from prefill to decode (the expensive-to-move part — this is exactly what fast KV transfer layers like Mooncake exist to make cheap).

Now a giant prefill can't block anyone's decodes, because it physically runs on a different pool. Each pool can also be tuned and scaled independently for its own SLO (TTFT for prefill, ITL for decode) instead of compromising on one knob for both.

The simulation pins each request's decodes to the engine that ran its prefill (KV-cache locality) — the constraint that makes colocated blocking unavoidable:

if disaggregated {
if j.prefill {
server, dur = 0, w.prefill[j.req] // prefill pool
} else {
server, dur = 1, decodeDur        // decode pool — never behind a prefill
}
} else {
server = j.req % 2                    // pinned engine holds this request's KV cache
// ...its decodes are stuck behind whatever prefill lands here
}



The result


Prefill/Decode Disaggregation — keep long prefills from stalling the token stream
before → after:  p99 inter-token latency 88ms (colocated)  →  30ms (disaggregated)   (66% lower)
240 requests, 2 servers, 20% long-context bursts (700–1800ms prefill), 20 decode steps × 5ms.

layout                  p99 token lat mean token lat    mean TTFT
colocated (shared)              88 ms          15 ms       426 ms
disaggregated (split)           30 ms          11 ms      1032 ms

Same workload, same total hardware (2 engines each). Colocated lets bursty prefills jump ahead of tiny decodes, so the p99 token stutters to 88ms. Disaggregated isolates decodes and holds p99 to 30ms — a 66% smoother stream. The honest cost is TTFT: with only one engine dedicated to prefill, first tokens arrive later (426ms → 1032ms). That's the real knob disaggregation gives you — pool sizing lets you buy back TTFT by provisioning prefill and decode independently.



Why this is where 2026 is heading


Disaggregation went from research idea to default in two years. DistServe showed that separating prefill and decode and sizing each for its own SLO can serve multiples more requests under latency constraints; Splitwise made the same case for splitting the phases across different hardware. By 2026 it's productized: vLLM ships PD disaggregation, and the vLLM × Mooncake work pairs it with a distributed KV cache pool so prefill and decode engines — even on different machines — share caches over fast transport. The load-bearing enabler is exactly the KV-cache handoff this demo hand-waves.

The transferable idea generalizes past LLMs: when one queue mixes bursty heavy work with steady latency-sensitive work, isolate them. It's the same instinct as separating batch from interactive traffic, or OLAP from OLTP — applied at the token level.



How faithful is this demo?


It models queueing and head-of-line blocking, not GPUs: "prefill" and "decode" are service times, and it ignores continuous batching, the real (non-zero) cost of KV-cache transfer, and memory pressure — all of which real systems must handle, and which is why cheap KV transport matters so much. Two honest caveats: disaggregation isn't free (you pay a transfer and a TTFT hop, visible above), and it only pays off when prefill bursts actually contend with latency-sensitive decodes. Short, uniform prompts under light load won't show the gap — measure your ITL tail before splitting.



Try it


go run .   # standard library only



Sources & further reading


Papers

• Zhong et al. — DistServe: Disaggregating Prefill and Decoding for Goodput-optimized LLM Serving (OSDI 2024, arXiv 2401.09670) — the case for splitting the phases and sizing each pool for its own latency target.

• Patel et al. — Splitwise: Efficient Generative LLM Inference Using Phase Splitting (ISCA 2024, arXiv 2311.18677) — splits prefill and decode across distinct machines to raise throughput per dollar and per watt.

• Qin et al. — Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving (FAST 2025, arXiv 2407.00079) — trades more storage for less compute; the KV-cache pool that makes cross-engine handoff practical.

Engineering


Serving Agentic Workloads at Scale with vLLM × Mooncake (2026) — production PD disaggregation plus a distributed KV cache pool for multi-turn, agentic serving.


KV Cache Offloading: LMCache vs Mooncake vs Dynamo — how the KV-transfer tier underneath disaggregation actually works.


Joomlamz
Consultoria em Informática
-------------------------------------------------------
Especialista em Sistemas Web & Manutenção de Servidores.
A desenvolver o novo AplPortal com suporte a PHP 8.
Precisa de ajuda profissional? Contacte-me.

Tags: