Вирішення проблемПосібник
Обробка запитів у 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, тож сприймайте їх як розібраний приклад, а не як закон. Їхній аналіз першопричини теж їхній: супровідник назвав це «відомою проблемою» і закрив 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% (зайнято дев'ять-десять ядер). GPU, що простоює, поки ви «працюєте на GPU», — це симптом, який варто шукати.

Чому менший кеш робить це настільки повільнішим#
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Ця пара типів кешу не має ядра flash-attention для GPU у стандартній збірці
Виправлення 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 через пам'ять, перезберіть з усіма комбінаціями кешу для 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 зауважив, що перенесення роботи між бекендами може трохи змінити числові результати, і запропонував порівняти perplexity між збірками. Якщо вам важливі точні вихідні дані, зробіть це.
Порівняйте
Яке виправлення підходить вашій карті?
Кеш q8_0
Змініть --cache-type-k і --cache-type-v на q8_0. Без перезбирання. Використовує більше VRAM, ніж q5_1, тож перевірте розмір контексту, який вміщується.
Перезбирання з FA_ALL_QUANTS
Залиште q5_1 і зберіть з -. Той самий обсяг VRAM, що й раніше, але ви підтримуєте власну збірку, і компіляція триває довше.
Відповідь супровідника «відома проблема» не каже, чи змінили це поточні версії llama.cpp. Чесна перевірка — пара llama-bench вище: якщо обидва рядки близькі, у вас усе гаразд.
Коли тюнінг перестає бути вартим#
Припустімо, ви налагодили виправлення і тепер зважуєте наступний раунд: більше прапорців, друга GPU, менший квант. Якщо робота — це підсумки, рев'ю коду чи вилучення даних на запитах у кілька тисяч токенів, запитайте, скільки запит коштує вам у часі та зусиллях, а не лише у ватах.
Ось заявлене навантаження для порівняння. Скажімо, завдання підсумовування надсилає 3,600 вхідних токенів і отримує 500 назад, 1,000 разів. На CheapTokens це близько $0.104 на DeepSeek-V4-Flash (контекст 380K, до 32,768 вихідних токенів на відповідь, одна ціна в будь-яку годину) і близько $0.092 на GLM-5.3-Flash (контекст 390K). Таблиця рахує вхід і вихід разом, з колонкою OpenRouter для порівняння:
| Модель | Вхід $/1М | Вихід $/1М | За запит | 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 вихідних токенів на запит. Ціни за 1 млн токенів актуальні та змінюються разом із нашими тарифами; стовпець OpenRouter показує довідкові ціни для того самого навантаження.
API не хвилює ваш тип кешу, ваша VRAM чи прапорці збірки; немає чого переносити на CPU. Спершу надішліть кілька своїх реальних запитів і оцініть відповіді самі. Крок невеликий: ендпоінт говорить форматом OpenAI Chat Completions, тож більшості локальних клієнтів потрібна лише нова базова 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 дивіться Запуск DeepSeek локально або через API. Якщо хочете побачити, як вхід і вихід тарифікуються окремо, вхідні vs вихідні токени це пояснює.
Порядок дій#
Розставте по порядку
Розставте кроки усунення несправностей по порядку
Перетягніть елементи або скористайтеся стрілками
- Запустіть llama-bench для q8_0 і q5_1 і стежте за nvidia-smi
- Перемкніть обидва типи кешу на q8_0
- Перевірте, чи довжина контексту все ще вміщується у VRAM
- Перезберіть з GGML_CUDA_FA_ALL_QUANTS=ON, лише якщо вам потрібен q5_1
- Порівняйте той самий запит на API, якщо локальне налаштування все ще не варте зусиль
Ще одне застереження щодо джерел: увесь діагноз спирається на один публічний issue і одну GPU. Сприймайте 1348 і 38.4 як те, що сталося там, і виміряйте власну карту, перш ніж довіряти будь-чому з цього.



