Prefill
Jak działa
W fazie prefill model wykonuje jeden (lub kilka, przy chunked prefill) przebieg forward na całej sekwencji promptu o długości N. Ponieważ wszystkie tokeny wejściowe są znane z góry, obliczenia uwagi i warstw MLP realizuje się jako duże mnożenia macierzy o wysokim wykorzystaniu jednostek (compute-bound). W trakcie tego przebiegu dla każdej warstwy zapisuje się klucze i wartości (K, V) wszystkich N tokenów do KV cache. Na końcu model produkuje rozkład prawdopodobieństwa następnego tokenu i próbkuje pierwszy wygenerowany token. Następnie sterowanie przechodzi do fazy decode, która generuje kolejne tokeny po jednym, korzystając z zapełnionego KV cache. Koszt obliczeniowy prefill rośnie z długością promptu (uwaga ~O(N^2)).
Rozwiązany problem
Generacja autoregresyjna wymaga, by model przed wyprodukowaniem pierwszego tokenu przetworzył cały prompt i zbudował reprezentację kontekstu. Faza prefill robi to efektywnie, przetwarzając wszystkie tokeny promptu naraz (równolegle) zamiast jeden po drugim, i zapisując klucze oraz wartości uwagi w KV cache, aby faza decode nie musiała ich przeliczać. Prefill wyznacza opóźnienie do pierwszego tokenu i mocno obciąża jednostki obliczeniowe.
Kluczowe mechanizmy
Mocne strony i ograniczenia
Komponenty
Jednoczesne przetworzenie wszystkich N tokenów promptu w jednym przebiegu, realizowane jako duże mnożenia macierzy.
Zapis kluczy i wartości uwagi wszystkich tokenów promptu dla każdej warstwy, aby uniknąć ich przeliczania w fazie decode.
Wyznaczenie rozkładu następnego tokenu z ostatniej pozycji i wypróbkowanie pierwszego wyjścia, wyznaczające TTFT.
Implementacja
Pojedynczy długi prefill może zająć GPU na długo i zwiększyć opóźnienia tokenów innych zapytań w batchu.
Powtarzalne prefiksy (np. wspólny prompt systemowy) przeliczane od nowa marnują moc obliczeniową prefill.
Ewolucja
Wraz z upowszechnieniem generatywnych transformerów uwidacznia się podział inferencji na compute-bound prefill i memory-bound decode.
Prace nad efektywnym serwowaniem (m.in. vLLM, Sarathi, DistServe) wprowadzają chunked prefill i rozdzielenie prefill/decode dla lepszego wykorzystania GPU.
Hiperparametry (konfigurowalne osie)
Liczba tokenów promptu przetwarzanych w jednym fragmencie przy przeplataniu z decode.
Współdzielenie KV cache wspólnych prefiksów między zapytaniami.
Złożoność obliczeniowa
Złożoność czasowa: O(N^2 d) uwaga + O(N d^2) projekcje. Złożoność przestrzenna: O(N x L x d) na KV cache promptu.
TTFT zdominowane przez prefill rośnie z długością promptu; dla długich kontekstów człon O(N^2) uwagi staje się zauważalny. Prefix caching wspólnego promptu systemowego może zredukować czas prefill do niemal zera dla powtarzalnych prefiksów, a chunked prefill wygładza opóźnienia tokenów innych zapytań przez przeplatanie fragmentów prefill z krokami decode.
Wąskie gardło obliczeniowe
Prefill jest ograniczony mocą obliczeniową: duże mnożenia macierz-macierz uwagi i MLP wysycają jednostki Tensor Core.
Paradygmat wykonania
Wszystkie tokeny i ścieżki obliczeń są aktywne jednocześnie.
Prefill wykonuje gęsty przebieg forward bez warunkowego routingu (chyba że model jest MoE).
Równoległość
Wszystkie tokeny promptu przetwarzane są jednocześnie, co czyni prefill wysoce równoległym i compute-bound.
Wymagania sprzętowe
Duże mnożenia macierzy fazy prefill maksymalnie wykorzystują rdzenie Tensor Core; to faza, w której GPU osiąga wysoki FLOPs utilization.
Równoległy, compute-bound charakter prefill dobrze pasuje do jednostek MXU w TPU.