Решение проблемИнструкция
llama.cpp: обработка промпта медленнее в 35 раз? KV-кэш q5_1
Flash attention и KV-кэш q5_1 могут увести внимание на CPU. Как это проверить, исправить через q8_0 и когда проще взять API.

Содержание
Локальная модель отвечает нормально, но на каждый длинный промпт уходит полторы минуты, а GPU простаивает. Если вы запускаете llama.cpp с -fa on и KV-кэшем q5_1, причина, скорее всего, в этом: в стандартной CUDA-сборке нет ядра flash attention для такого типа кэша, и шаг внимания тихо выполняется на CPU. Переход на q8_0 поднял обработку промпта у автора отчёта с 38 до 1348 токенов/с.
Цифры ниже — из issue #28455 в llama.cpp (открыт 5 сентября 2026, сборка 10791, проверено 28 октября 2026). Один автор отчёта, одна RTX 4080, одна модель на 27B, так что это разобранный пример, а не закон. Анализ причины тоже принадлежит автору: мейнтейнер назвал это «known issue» и закрыл issue на следующий день.
Как это выглядит на экране#
Настройка обычная. Человек хотел контекст в 131072 токена на одной карте с 16 ГБ и сжал KV-кэш до q5_1:
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
--cache-type-k q5_1 --cache-type-v q5_1Потом отправил промпт на 3,6K токенов. Обработка промпта шла со скоростью 38,4 токена/с, генерация — 6,5 токена/с. Считаем: 3 600 ÷ 38,4 = 93,75, то есть около 94 секунд до первого слова. С q8_0 тот же промпт обработался на 1348 токенов/с: 3 600 ÷ 1 348 = 2,67, меньше трёх секунд.
Улика — в диспетчере задач. Во время медленных прогонов GPU был загружен около 0%, а CPU показывал примерно 930% (заняты девять-десять ядер). Видеокарта простаивает, пока вы «считаете на видеокарте» — вот что нужно искать.

Почему меньший кэш даёт такое замедление#
Flash attention — это объединённое ядро для GPU. Стандартная CUDA-сборка содержит его только для части пар типов KV-кэша. Для q4_0, q4_1, q5_0 и q5_1 ядра нет, и llama.cpp не останавливается с ошибкой: он переносит эту операцию на CPU и продолжает. Всё работает, просто примерно в 35 раз медленнее на обработке промпта (1348 ÷ 38,4 = 35,1).
Именно это «тихо» и есть проблема. В ответе об этом ни слова, сильнее всего проседает обработка промпта (примерно в 35 раз), но и генерация замедляется: 6,5 токена/с против 30,1 с q8_0 в том же issue.
Проверка за две минуты#
Запустите llama-bench с теми же типами кэша, что и в сервере, по одному разу на вариант, а в соседнем терминале смотрите на GPU:
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 1Результаты pp512 автора отчёта на Qwen 27B Q5_K_XL: 1511,92 токена/с для q8_0/q8_0 и около 197 для q5_1/q5_1 в стандартной сборке. Если у вас две строки показывают такой разрыв, а nvidia-smi во время второй показывает простаивающий GPU, причина найдена.
Прежде чем что-то чинить, сопоставьте симптом с вероятной причиной:
Найдите пары
Сопоставьте симптом и причину
Нажмите на элемент слева, затем на его пару
- GPU около 0%, CPU около 930% на длинном промптеВнимание выполняется на CPU
- Генерация падает до 6,5 токена/с против 30,1 с
q8_0Замедляется и генерация, а не только обработка промпта - С теми же флагами и
q8_0быстроДля этой пары типов кэша в стандартной сборке нет GPU-ядра flash attention
Исправление 1: q8_0 (или пересборка)#
Быстрее всего поменять два флага и оставить остальное:
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
--cache-type-k q8_0 --cache-type-v q8_0В issue это дало 1348 токенов/с на обработке промпта и 30,1 токена/с на генерации (было 6,5). Плата — память: кэш q8_0 больше, чем q5_1, поэтому проверьте, что выбранная длина контекста по-прежнему помещается в VRAM.
Если q5_1 нужен из-за памяти, пересоберите llama.cpp со всеми комбинациями кэша для flash attention:
cmake -B build -DGGML_CUDA=ON -DGGML_CUDA_FA_ALL_QUANTS=ON
cmake --build build --config Release -jНа такой сборке q5_1 дал 1509,70 токена/с на pp512 и 1162 токена/с на промпте в 3,6K токенов, генерация — 38,5 токена/с. Один из комментаторов issue заметил, что перенос работы между бэкендами может немного изменить численные результаты, и предложил сравнить перплексию между сборками. Если вам важны точные выходы, сделайте это сравнение.
Сравнение
Какое исправление подходит вашей карте?
Кэш q8_0
Поменяйте --cache-type-k и --cache-type-v на q8_0. Пересборка не нужна. VRAM нужно больше, чем для q5_1, поэтому перепроверьте, какой контекст помещается.
Пересборка с FA_ALL_QUANTS
Оставьте q5_1 и соберите с -. VRAM как раньше, но вы поддерживаете собственную сборку, и компилируется она дольше.
Ответ мейнтейнера про «known issue» не уточняет, изменили ли это в текущих версиях llama.cpp. Честная проверка — пара запусков llama-bench выше: если обе строки близки, всё в порядке.
Когда настройка перестаёт окупаться#
Допустим, исправление сработало, и вы думаете о следующем круге: ещё флаги, вторая видеокарта, квант поменьше. Если задача — сводки, ревью кода или извлечение данных из промптов в несколько тысяч токенов, прикиньте цену запроса во времени и усилиях, а не только в ваттах.
Вот заданная нагрузка для сравнения. Допустим, задача суммаризации отправляет 3 600 токенов на входе и получает 500 на выходе, 1 000 раз. В CheapTokens это примерно $0.104 на DeepSeek-V4-Flash (контекст 380K, до 32 768 токенов в ответе, одна цена в любое время суток) и примерно $0.092 на GLM-5.3-Flash (контекст 390K). В таблице вход и выход считаются вместе, рядом колонка OpenRouter для сравнения:
| Модель | Вход $/1M | Выход $/1M | За запрос | 1 000 запросов | OpenRouter, 1 000 запросов |
|---|---|---|---|---|---|
| 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 |
3 600 входных и 500 выходных токенов на запрос. Цены за 1M токенов актуальны и меняются вместе с нашими тарифами; столбец OpenRouter показывает справочные цены для той же нагрузки.
API не зависит от вашего типа кэша, объёма VRAM и флагов сборки: на CPU там падать нечему. Отправьте для начала пару своих настоящих промптов и оцените ответы сами. Шаг небольшой: эндпоинт понимает формат OpenAI Chat Completions, так что большинству локальных клиентов нужен только новый base 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}'Полная настройка — в документации CheapTokens, актуальные цены по моделям — на странице цен. Подробнее о железе против API — в статье Run DeepSeek locally or use an API. Как отдельно считаются вход и выход, разбирает input vs output tokens.
Порядок действий#
Расставьте по порядку
Расставьте шаги диагностики по порядку
Перетащите элементы или используйте стрелки
- Запустить llama-bench для q8_0 и q5_1 и смотреть nvidia-smi
- Переключить оба типа кэша на q8_0
- Проверить, что длина контекста помещается в VRAM
- Пересобрать с GGML_CUDA_FA_ALL_QUANTS=ON, только если нужен q5_1
- Сравнить тот же промпт на API, если локальная настройка всё ещё не стоит усилий
Ещё одна оговорка об источниках: весь диагноз держится на одном публичном issue и одной видеокарте. Считайте 1348 и 38,4 тем, что произошло там, и измерьте свою карту, прежде чем верить любому из чисел.



