𝗞𝗩 𝗖𝗮𝗰𝗵𝗲 𝗮𝗻𝗱 𝗣𝗮𝗴𝗲𝗱𝗔𝘁𝘁𝗲𝗻𝘁𝗶𝗼𝗻: 𝗪𝗵𝘆 𝗬𝗼𝘂𝗿 𝗟𝗟𝗠 𝗦𝗲𝗿𝘃𝗲𝗿 𝗦𝗹𝗼𝘄𝘀 𝗗𝗼𝘄𝗻
Your LLM server is running slow.
You deployed a 70B model on four A100 GPUs. Everything looks fine at 8 AM. By lunch, latency doubles. You check your memory. Most of it is taken up by "tensor buffers." These are actually cached states from old conversations.
This is the KV cache problem. It is the biggest bottleneck in production LLM serving.
What is the KV cache?
Every transformer model generates tokens one by one. To create a new token, the model needs the Key and Value tensors from all previous tokens. Recomputing these every time is too slow. Instead, the engine stores them. This storage is the KV cache.
The memory problem:
For a Llama 3.1 70B model, a single 4096-token sequence needs about 1.3 GB of memory.
If you have 256 users at once, you need 336 GB of memory. This is more than four A100 GPUs can hold. The KV cache grows so fast that it often uses more memory than the model weights themselves.
Traditional memory management fails because:
- Internal fragmentation: You allocate space for 4096 tokens but only use 300. You waste 93% of that space.
- No sharing: Two users with the same system prompt each store their own copy of that prompt.
- All-or-nothing eviction: When memory runs out, you must move the entire sequence to the CPU. This stalls the GPU.
How PagedAttention fixes this:
PagedAttention works like an operating system. It divides the KV cache into small, fixed-size blocks called pages.
This solves three main issues:
- On-demand allocation: A sequence only takes up pages as it grows. You do not waste memory on unused capacity.
- Shared prefix support: Multiple users can share the same physical pages for a common system prompt. This uses "copy-on-write" logic to save massive amounts of memory.
- Fine-grained eviction: When memory is full, the system moves small pages to the CPU instead of huge sequences.
The Result:
Using PagedAttention (the tech inside vLLM) can increase throughput by 2x to 4x compared to traditional methods.
When to use it:
- High concurrency.
- Sequences of different lengths.
- Prompts that share the same start.
When to skip it:
- Single-user local inference.
- Very small models.
- Tasks where every sequence is exactly the same length.
KV Cache i PagedAttention: Co robią i dlaczego są ważne
W świecie dużych modeli językowych (LLM), wydajność jest wszystkim. Podczas gdy modele te stają się coraz większe i bardziej zdolne, wyzwania związane z ich wdrażaniem i generowaniem tekstu (inferencją) rosną proporcjonalnie. Dwa kluczowe pojęcia, które rewolucjonizują sposób, w jaki zarządzamy zasobami podczas inferencji, to KV Cache oraz PagedAttention.
W tym artykule przyjrzymy się temu, czym są te technologie, jakie problemy rozwiązują i dlaczego mają tak ogromne znaczenie dla współczesnej sztucznej inteligencji.
Problem: Autoregresyjna natura LLM
Aby zrozumieć KV Cache, musimy najpierw zrozumieć, jak LLM generują tekst. Proces ten jest autoregresyjny. Oznacza to, że model generuje jeden token na raz, a następnie dodaje ten token do sekwencji wejściowej, aby wygenerować kolejny.
Wyobraź sobie, że prosisz model o dokończenie zdania: "Ala ma...".
- Model analizuje "Ala ma" i generuje token "kota".
- Następnie model analizuje "Ala ma kota" i generuje token "i".
- Następnie model analizuje "Ala ma kota i" i generuje token "psa".
Zauważ, że przy każdym nowym kroku model musi ponownie przetwarzać wszystkie poprzednie tokeny, aby zrozumieć kontekst. Bez optymalizacji, obliczenia te stawałyby się coraz bardziej kosztowne i powolne wraz z wydłużaniem się tekstu.
Czym jest KV Cache?
Tutaj wchodzi KV Cache (Key-Value Cache).
W architekturze Transformer, mechanizm Attention (uwagi) polega na obliczaniu relacji między tokenami. Do tego celu używane są trzy wektory: Query (Q), Key (K) oraz Value (V).
Podczas generowania każdego nowego tokena, wartości K i V dla wszystkich poprzednich tokenów pozostają takie same. Zamiast przeliczać je od zera przy każdym kroku, możemy je po prostu zapisać w pamięci.
- Key (K): Reprezentuje informacje o tym, co dany token "oferuje" innym tokenom.
- Value (V): Reprezentuje faktyczną treść informacji, którą dany token niesie.
Dzięki KV Cache, model musi obliczyć wektory K i V tylko raz dla każdego tokena. Przy kolejnych krokach po prostu pobiera je z pamięci, co drastycznie przyspiesza proces generowania.
Problem: Marnotrawstwo pamięci
Mimo że KV Cache jest niezwykle pomocny, wprowadza on nowy problem: ogromne zapotrzebowanie na pamięć VRAM.
Rozmiar KV Cache rośnie liniowo wraz z:
- Długością sekwencji (im dłuższy tekst, tym więcej danych).
- Rozmiarem partii (batch size) (im więcej użytkowników obsługujemy jednocześnie, tym więcej pamięci potrzebujemy).
W tradycyjnych systemach, pamięć dla KV Cache musi być zarezerwowana "z góry" (pre-allocation). System musi przewidzieć maksymalną możliwą długość sekwencji dla każdego zapytania. To prowadzi do dwóch głównych problemów:
- Fragmentacja wewnętrzna: Rezerwujemy miejsce na 2048 tokenów, ale użytkownik generuje tylko 100. Reszta pamięci jest bezużytecznie zajęta.
- Fragmentacja zewnętrzna: Pamięć jest podzielona na małe, nieciągłe kawałki, co uniemożliwia przydzielenie dużych bloków dla nowych zadań, nawet jeśli całkowita wolna pamięć jest wystarczająca.
To sprawia, że wykorzystanie pamięci GPU jest bardzo nieefektywne, co ogranicza liczbę użytkowników, których możemy obsłużyć jednocześnie (przepustowość).
Rozwiązanie: PagedAttention
Tutaj pojawia się PagedAttention, technologia wprowadzona m.in. przez bibliotekę vLLM.
PagedAttention czerpie inspirację z pamięci wirtualnej stosowanej w systemach operacyjnych. W systemach operacyjnych pamięć fizyczna nie musi być ciągła; jest ona dzielona na małe jednostki zwane "stronami" (pages), które mogą być rozmieszczone w dowolnym miejscu w pamięci RAM.
Jak działa PagedAttention?
Zamiast rezerwować jeden wielki, ciągły blok pamięci dla całego KV Cache danej sekwencji, PagedAttention dzieli go na mniejsze, stałe bloki.
- Bloki pamięci: KV Cache jest dzielony na bloki o stałym rozmiarze (np. odpowiadające 16 tokenom).
- Tablica stron (Page Table): System utrzymuje tablicę, która mapuje logiczną sekwencję tokenów na fizyczne bloki w pamięci GPU.
- Nieciągłość: Bloki te nie muszą leżeć obok siebie w pamięci VRAM. Mogą być rozproszone, a PagedAttention "skleja" je logicznie podczas obliczeń.
Dlaczego to zmienia zasady gry?
- Minimalna fragmentacja: Ponieważ bloki są małe i przydzielane na żądanie, marnotrawstwo pamięci ogranicza się niemal wyłącznie do ostatniego bloku w sekwencji.
- Dynamiczne zarządzanie: Możemy przydzielać pamięć dokładnie wtedy, gdy jest potrzebna, a nie na samym początku.
- Współdzielenie pamięci (Memory Sharing): PagedAttention pozwala na bardzo efektywne współdzielenie bloków pamięci między różnymi zapytaniami. Jest to niezwykle przydatne w zadaniach takich jak Parallel Sampling (generowanie wielu odpowiedzi na to samo pytanie) lub Beam Search, gdzie wiele sekwencji zaczyna się od tego samego tekstu.
Podsumowanie
Bez KV Cache, generowanie tekstu przez LLM byłoby zbyt wolne, by było praktyczne. Jednak to KV Cache stworzył problem ogromnego marnotrawstwa pamięci.
PagedAttention rozwiązuje ten problem, wprowadzając inteligentne zarządzanie pamięcią wzorowane na systemach operacyjnych. Dzięki temu możemy:
- Drastycznie zwiększyć przepustowość (throughput) serwerów LLM.
- Obsłużyć znacznie większą liczbę użytkowników na tym samym sprzęcie.
- Efektywniej wykorzystywać kosztowną pamięć VRAM procesorów graficznych.
Zrozumienie tych mechanizmów jest kluczowe dla każdego, kto zajmuje się optymalizacją i wdrażaniem modeli AI w skali produkcyjnej.
Opcjonalna społeczność edukacyjna: https://t.me/GyaanSetuAi