Rozwiązywanie problemówPrzewodnik
Przetwarzanie promptu w llama.cpp 35x wolniejsze? Napraw pamięć KV q5_1
Flash attention plus pamięć KV q5_1 może przenieść uwagę na CPU. Jak to potwierdzić, naprawić przez q8_0 i kiedy API jest prostsze.

Na tej stronie
Twój lokalny model odpowiada poprawnie, ale każdy długi prompt wisi teraz przez półtorej minuty, podczas gdy GPU nic nie robi. Jeśli uruchamiasz llama.cpp z -fa on i pamięcią KV q5_1, to prawdopodobnie przyczyna: domyślna kompilacja CUDA nie ma jądra flash-attention dla tego typu pamięci, więc krok uwagi po cichu wykonuje się na CPU. Przełączenie pamięci na q8_0 podniosło u jednego zgłaszającego przetwarzanie promptu z 38 do 1348 tokenów/s.
Poniższe liczby pochodzą z issue #28455 w llama.cpp (otwarte 5 września 2026, kompilacja 10791, sprawdzone 28 października 2026). Jeden zgłaszający, jedna RTX 4080, jeden model 27B, więc czytaj je jako przykład, nie jako regułę. Ich analiza przyczyny źródłowej też jest ich własna: opiekun nazwał to „znanym problemem” i zamknął issue następnego dnia.
Jak to wygląda na ekranie#
Konfiguracja była zwyczajna. Ktoś chciał kontekst 131072 tokenów na jednej karcie 16 GB, więc zmniejszył pamięć KV do q5_1:
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
--cache-type-k q5_1 --cache-type-v q5_1Potem wysłał prompt o 3,6K tokenów. Przetwarzanie promptu działało z prędkością 38,4 tokena/s, a dekodowanie z 6,5 tokena/s. Policz: 3 600 ÷ 38,4 = 93,75, czyli około 94 sekund do pierwszego słowa. Z q8_0 ten sam prompt działał z prędkością 1348 tokenów/s: 3 600 ÷ 1 348 = 2,67, poniżej trzech sekund.
Objaw widać w menedżerze zadań. Podczas wolnych przebiegów GPU było blisko 0%, a CPU pokazywało około 930% (zajęte dziewięć lub dziesięć rdzeni). GPU, które nic nie robi, gdy „działasz na GPU”, to objaw, którego szukasz.

Dlaczego mniejsza pamięć powoduje aż takie spowolnienie#
Flash attention to zintegrowane jądro GPU. Domyślna kompilacja CUDA dostarcza je tylko dla niektórych par typów pamięci KV. Dla q4_0, q4_1, q5_0 i q5_1 nie ma jądra, więc llama.cpp nie zatrzymuje się z błędem. Przenosi tę operację na CPU i działa dalej. Wszystko nadal działa, tylko około 35 razy wolniej przy przetwarzaniu promptu (1348 ÷ 38,4 = 35,1).
To „po cichu” jest całym problemem. Nic w odpowiedzi ci tego nie mówi. Przetwarzanie promptu spada najbardziej (około 35×), a generowanie też zwalnia: 6,5 tokena/s wobec 30,1 z q8_0 w tym samym issue.
Sprawdź to w dwie minuty#
Uruchom llama-bench z tymi samymi typami pamięci, których używasz w serwerze, raz na wariant, i obserwuj GPU w innym terminalu:
llama-bench -m model.gguf -ngl 99 -fa 1 -ctk q8_0 -ctv q8_0 -p 512 -n 0
llama-bench -m model.gguf -ngl 99 -fa 1 -ctk q5_1 -ctv q5_1 -p 512 -n 0
nvidia-smi -l 1Wyniki pp512 zgłaszającego na Qwen 27B Q5_K_XL: 1511,92 tokena/s dla q8_0/q8_0, około 197 dla q5_1/q5_1 w domyślnej kompilacji. Jeśli twoje dwie linie pokazują taką różnicę, a nvidia-smi pokazuje bezczynne GPU podczas drugiej, to właśnie to znalazłeś.
Zanim cokolwiek naprawisz, dopasuj to, co widzisz, do prawdopodobnej przyczyny:
Dopasuj pary
Dopasuj każdy objaw do jego przyczyny
Dotknij element po lewej, a następnie jego parę
- GPU na ~0%, CPU na ~930% podczas długiego promptuUwaga działa na CPU
- Dekodowanie spada do ~6,5 tokena/s wobec 30,1 z
q8_0Generowanie też zwalnia, nie tylko przetwarzanie promptu - Te same flagi są szybkie z
q8_0Ta para typów pamięci nie ma jądra flash-attention na GPU w domyślnej kompilacji
Poprawka 1: użyj q8_0 (albo przebuduj)#
Najszybsza poprawka to zmiana dwóch flag i zachowanie całej reszty:
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
--cache-type-k q8_0 --cache-type-v q8_0W issue dało to 1348 tokenów/s przy przetwarzaniu promptu i 30,1 tokena/s przy dekodowaniu (wzrost z 6,5). Ceną jest pamięć: pamięć q8_0 jest większa niż q5_1, więc sprawdź, czy twoja długość kontekstu nadal mieści się w VRAM.
Jeśli musisz zachować q5_1 ze względu na pamięć, przebuduj z wszystkimi kombinacjami pamięci flash-attention wkompilowanymi:
cmake -B build -DGGML_CUDA=ON -DGGML_CUDA_FA_ALL_QUANTS=ON
cmake --build build --config Release -jTa kompilacja uruchomiła q5_1 z prędkością 1509,70 tokena/s na pp512 i 1162 tokenów/s na prompcie o 3,6K tokenów, z dekodowaniem na poziomie 38,5 tokena/s. Komentujący w issue zauważył, że przenoszenie pracy między backendami może nieco zmienić wyniki numeryczne, i zasugerował porównanie perplexity między kompilacjami. Jeśli zależy ci na dokładnych wynikach, zrób takie porównanie.
Porównaj
Która poprawka pasuje do twojej karty?
Pamięć q8_0
Zmień --cache-type-k i --cache-type-v na q8_0. Bez przebudowy. Zużywa więcej VRAM niż q5_1, więc ponownie sprawdź, jaki rozmiar kontekstu się zmieści.
Przebudowa z FA_ALL_QUANTS
Zachowaj q5_1 i zbuduj z -. Tyle samo VRAM co wcześniej, ale utrzymujesz własną kompilację i kompilacja trwa dłużej.
Odpowiedź opiekuna „znany problem” nie mówi, czy obecne wersje llama.cpp to zmieniły. Uczciwym sprawdzeniem jest para llama-bench powyżej: jeśli obie linie są blisko siebie, wszystko jest w porządku.
Kiedy dostrajanie przestaje się opłacać#
Powiedzmy, że poprawka zadziałała i teraz rozważasz kolejną rundę: więcej flag, druga GPU, mniejsza kwantyzacja. Jeśli zadanie to streszczenia, przegląd kodu lub ekstrakcja na promptach o kilku tysiącach tokenów, zapytaj, ile żądanie kosztuje cię czasu i wysiłku, a nie tylko watów.
Oto podane obciążenie do porównania. Powiedzmy, że zadanie streszczania wysyła 3600 tokenów wejściowych i dostaje 500 z powrotem, 1000 razy. W CheapTokens to około $0.104 na DeepSeek-V4-Flash (kontekst 380K, do 32 768 tokenów wyjściowych na odpowiedź, jedna cena o każdej porze) i około $0.092 na GLM-5.3-Flash (kontekst 390K). Tabela liczy wejście i wyjście razem, z kolumną OpenRouter do porównania:
| Model | Wejście $/1M | Wyjście $/1M | Za żądanie | 1000 żądań | OpenRouter, 1000 żądań |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.000092 | $0.092 | $0.187 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0001 | $0.104 | $0.249 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.00026 | $0.255 | $1.68 |
3600 tokenów wejściowych i 500 tokenów wyjściowych na żądanie. Ceny za 1 mln tokenów są aktualne i zmieniają się wraz z naszymi taryfami; kolumna OpenRouter pokazuje ceny referencyjne dla tego samego obciążenia.
API nie obchodzi twój typ pamięci, twoja VRAM ani flagi kompilacji; nie ma czego przenosić na CPU. Najpierw wyślij kilka swoich prawdziwych promptów i sam oceń odpowiedzi. Krok jest mały: endpoint mówi w formacie OpenAI Chat Completions, więc większość lokalnych klientów potrzebuje tylko nowego bazowego URL.
curl https://api.cheaptokens.dev/v1/chat/completions \
-H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "deepseek-ai/DeepSeek-V4-Flash-0731", "messages": [{"role": "user", "content": "Summarize the text below in 5 bullets: ..."}], "max_tokens": 500}'Pełna konfiguracja jest w dokumentacji CheapTokens, a aktualne ceny poszczególnych modeli na stronie z cenami. Szersze spojrzenie na sprzęt kontra API znajdziesz w Run DeepSeek locally or use an API. Jeśli chcesz zobaczyć, jak wejście i wyjście są rozliczane osobno, input vs output tokens to omawia.
Kolejność działań#
Ustaw w kolejności
Ułóż kroki rozwiązywania problemów w kolejności
Przeciągnij elementy lub użyj strzałek
- Uruchom llama-bench dla q8_0 i q5_1 i obserwuj nvidia-smi
- Przełącz oba typy pamięci na q8_0
- Sprawdź, czy długość kontekstu nadal mieści się w VRAM
- Przebuduj z GGML_CUDA_FA_ALL_QUANTS=ON tylko jeśli potrzebujesz q5_1
- Porównaj ten sam prompt na API, jeśli lokalna konfiguracja nadal nie jest warta wysiłku
Jeszcze jedno ostrzeżenie o źródłach: cała diagnoza opiera się na jednym publicznym issue i jednej GPU. Traktuj 1348 i 38,4 jako to, co wydarzyło się tam, i zmierz własną kartę, zanim zaufasz któremukolwiek z nich.



