O problema que PagedAttention resolve: quando uma requisição chega, você não sabe quão longa a resposta será, então precisa pré-alocar KV cache para o comprimento máximo possível. Se o comprimento máximo é 4096 tokens mas a resposta é apenas 200 tokens, 95% da memória alocada é desperdiçada. Multiplique por centenas de requisições simultâneas e a memória GPU enche rápido, limitando o throughput.
PagedAttention divide o KV cache em páginas de tamanho fixo (ex.: 16 tokens por página). Páginas são alocadas apenas quando necessárias e podem ser armazenadas em qualquer lugar da memória GPU (não contíguo). Uma tabela de páginas mapeia posições lógicas para localizações de memória física, assim como a memória virtual do SO. Isso elimina fragmentação: memória é alocada página a página conforme a resposta cresce, e páginas liberadas ficam imediatamente disponíveis para novas requisições.
Uma extensão poderosa: quando múltiplas requisições compartilham o mesmo prefixo de prompt (comum com prompts de sistema compartilhados), suas páginas de KV cache para esse prefixo podem ser fisicamente compartilhadas — armazenadas uma vez na memória mas referenciadas por todas as requisições. Essa é a semântica copy-on-write do design de SO aplicada ao serving de LLM. Para aplicações onde muitos usuários compartilham o mesmo prompt de sistema, isso pode reduzir o uso de memória em 50%+ para a parte compartilhada.