# llama.cpp KV-кеш: квантизация K/V и проверка памяти

Источник: https://modelium.tech/zhurnal/llama-cpp-kv-cache/

В llama.cpp типы K и V для KV-кеша задаются отдельно флагами --cache-type-k и --cache-type-v; по умолчанию оба f16. Квантизация может сократить память под кеш при длинном контексте, но не задаёт универсальный объём RAM/VRAM и не гарантирует сохранение качества или ускорение. Сравните одинаковую модель и нагрузку сначала с f16, затем с q8_0 и q4_0, проверяя логи выделения памяти и ответы.

**Источники проверены по Git-ревизии **`**0504396**`** 4 октября 2026 года.** Ниже — процедура для собственного стенда, не результаты измерений Modelium. При обновлении llama.cpp сверяйте список поддерживаемых типов и поведение backend заново [s1](#src-s1)[s2](#src-s2).

## Что именно квантуется и кому это нужно?

При генерации llama.cpp сохраняет ключи и значения attention в KV-кеше. В отличие от [квантизации весов GGUF](/zhurnal/gguf-i-kvantovanie/), параметры `--cache-type-k` и `--cache-type-v` меняют тип данных **кеша для текущего контекста**, а не исходный файл модели. По документации `llama-server` оба типа по умолчанию `f16`; в перечне допустимых значений есть `q8_0`, `q4_0`, `q5_0` и другие. Типы K и V выбираются независимо. Это не инструкция переквантовать GGUF и не основание обещать неизменный ответ [s1](#src-s1)[s2](#src-s2)[s6](#src-s6).

Практическая задача — поместить выбранную модель и нужную длину контекста в имеющиеся ресурсы, не потеряв пригодность ответов. Путь: собственные запросы → один точный файл GGUF и его ревизия → память CPU/GPU и требуемый контекст → сервер llama.cpp → логи KV и проверенные ответы. Если не определили модель или backend, начните с [общего запуска llama.cpp](/zhurnal/llama-cpp/) и только потом меняйте тип кеша. Размер файла весов **не равен** минимальной RAM/VRAM: кроме весов будут кеш, рабочие буферы, размещение слоёв и другое потребление процесса [s1](#src-s1)[s3](#src-s3)[s5](#src-s5).

## Как выбрать f16, q8_0 или q4_0 без ложных гарантий?

`f16/f16` — контрольный режим, совпадающий с параметрами K/V по умолчанию. `q8_0/q8_0` и `q4_0/q4_0` — две отдельные экспериментальные конфигурации, а не обязательная последовательность улучшений. В закреплённом исходнике **квантованный V требует Flash Attention**: режим `auto` включает его автоматически, а явный `off` приводит к ошибке. Наличие флага ещё не доказывает поддержку выбранным backend. При заданной архитектуре и количестве ячеек более компактный формат может уменьшить выделенный буфер, но отношение размеров **не переносится автоматически** на всю RAM или VRAM; исходник выделяет тензоры по слоям и сообщает K/V отдельно. Не переносите измерения чужой модели, длины контекста или backend на свою машину [s1](#src-s1)[s3](#src-s3)[s6](#src-s6)[s7](#src-s7).

Для первого сравнения используйте симметричные пары, явно фиксируя, что K и V меняются вместе; это сравнение конфигураций, а не оценка вклада каждой компоненты. Если требуется оценить эффект **только K**, сравните `q8_0/f16` с `f16/f16` при остальных равных условиях, затем отдельно меняйте V. Смешанный `q8_0/f16` допустим в перечне независимых параметров, но совместимость и скорость конкретной комбинации зависят от backend и сборки. Проверка качества важнее формального уменьшения буфера: возьмите длинные контексты со ссылками на факты, задачами извлечения и повторным обращением к началу документа, а не только один короткий приветственный запрос [s1](#src-s1)[s2](#src-s2)[s3](#src-s3).

`--no-kv-offload` отключает выгрузку KV на ускоритель, но не квантует и не уменьшает автоматически всю память системы. В исходном коде тип буфера берётся от CPU, либо от устройства слоя при включённом offload; поэтому сравнивайте **место** выделения вместе с числом MiB. Не объявляйте экономию VRAM, если кеш ушёл в RAM. Опция `--cache-ram` и reuse префикса описывают другой слой управления кешем; они не являются заменой выбору типа K/V [s1](#src-s1)[s3](#src-s3).

## Как подготовить сопоставимый локальный запуск?

Используйте один и тот же собранный бинарник `llama-server`, точный путь к разрешённому к использованию GGUF и одинаковые аппаратные настройки в каждой серии. В документации сборки есть отдельные пути CPU, CUDA и других backend; не меняйте backend посередине эксперимента. Замените `/PATH/TO/MODEL.gguf` на фактический локальный файл, не скачивайте случайную модель лишь ради этого теста. Если бинарник не поддерживает параметры из закреплённой ревизии, сначала проверьте версию через `llama-server --help` [s1](#src-s1)[s5](#src-s5).

Для контрольного сервера используйте **шаблон по документации**, который Modelium не запускал: `llama-server -m /PATH/TO/MODEL.gguf --host 127.0.0.1 --port 8080 -c 4096 -np 1 --cache-type-k f16 --cache-type-v f16 --flash-attn on`. На отдельном запуске замените обе последние пары `f16` на `q8_0`, а после фиксации логов — на `q4_0`. Остальные аргументы, включая GPU layers, контекст и число слотов, оставьте неизменными; `--flash-attn on` держите одинаковым во всех сериях. Если выбранная модель/сборка/backend отказывается стартовать с включённым Flash Attention или определённым типом, зафиксируйте ошибку как несовместимость, а не подменяйте параметры только в одной серии. Не открывайте тестовый сервер наружу: `127.0.0.1` — локальный адрес привязки [s1](#src-s1)[s2](#src-s2)[s5](#src-s5).

После каждого старта запросите `GET /health`: во время загрузки сервер может вернуть 503, после готовности — 200. Затем подайте **одинаковый** тестовый набор на `/completion` или совместимый с моделью `/v1/chat/completions`; `/completion` не является OpenAI-совместимым маршрутом. Не считайте HTTP 200 проверкой смысла: запишите ответ, ошибки и условия sampling. Между режимами полностью остановите процесс и поднимите его заново, иначе сравните прогретый кеш и остатки нагрузки вместо типов K/V [s1](#src-s1).

## Как измерить память, задержку и качество ответов?

В логах старта найдите выделенный `KV buffer size` для конкретного CPU/GPU backend и строку `size = ... MiB` с отдельными размерами `K` и `V`, количеством ячеек и слоёв. Эти числа позволяют сравнить **буфер KV при одинаковых условиях**, но не отражают полное потребление процесса. Дополнительно снимайте свободную/занятую память устройства и RAM до и после запуска своим обычным мониторингом; не выводите «минимальные требования» из одной строки лога. Даже при одинаковом GGUF число слотов, `-c`, аппаратный backend и offload меняют размещение и объём кеша [s1](#src-s1)[s3](#src-s3).

Зафиксируйте точный файл и ревизию модели, версию бинарника, backend/устройство, режим K/V, `-c`, `-np`, GPU layers, `--flash-attn`, входные запросы, sampling, число выходных токенов и загруженность системы. Для каждого режима сравните правильность извлечения фактов из длинного разрешённого документа, ссылки на фрагмент, удержание условий в начале контекста и долю отказов/ошибок. Собственный критерий: ни одна критичная задача не ухудшилась недопустимо относительно f16, а сокращение памяти реально позволило нужный контекст. Это **редакционный протокол**, не бенчмарк или обещание числа процентов от разработчиков [s1](#src-s1)[s3](#src-s3).

Для скорости сохраняйте задержку первого токена и полное время ответа при равной конкуренции. В серверных ответах есть объект `timings` с количеством и временем обработанных и предсказанных токенов; `--metrics` включает `/metrics` только если это нужно на закрытом стенде. Для более повторяемого pp/tg-сравнения `llama-bench` принимает `-ctk`, `-ctv` и `-d` (глубину заполненного контекста); prompt processing и generation — разные испытания. Запишите разброс повторов, не выдавайте токены/с за качество и не сравнивайте разные контекстные глубины как эффект одной квантизации [s1](#src-s1)[s4](#src-s4).

## Почему выигрыш не проявился или ответы испортились?

- **Буфер меньше, а общая память почти не изменилась:** веса и другие буферы остались прежними, часть KV могла находиться в RAM вместо VRAM. Проверьте строку backend, offload и внешнее измерение памяти, а не только размер GGUF [s1](#src-s1)[s3](#src-s3).

- **Квантованный тип не запустился:** сверьте допустимые значения в `--help`, Flash Attention, модель/архитектуру и поддержку выбранного backend. Сохраните лог ошибки; не утверждайте, что любой тип работает на любом устройстве [s1](#src-s1)[s2](#src-s2).

- **Скорость стала ниже:** дополнительная стоимость преобразования и путь выполнения на устройстве могут перекрыть уменьшение объёма кеша. Измерьте pp и tg отдельно на том же контексте; если условие эксперимента менялось, результат не атрибутируется квантизации [s1](#src-s1)[s4](#src-s4).

- **Ответы хуже при длинном контексте:** вернитесь к `f16/f16` или проверьте менее агрессивную пару `q8_0/q8_0` на том же наборе; не объявляйте низкую ошибку по одному короткому запросу доказательством качества на документах [s1](#src-s1)[s3](#src-s3).

## Какой следующий шаг после сравнения?

Запишите три конфигурации, логи размеров K/V и размещения, условия нагрузки, результаты одинаковых запросов и измерения доступной памяти. Оставляйте квантованный режим только если он работает на вашем backend и выбранной модели, даёт полезный выигрыш **в вашем** ограничении памяти и не нарушает критерий качества. Если проверка не пройдена, используйте контрольный f16 либо пересмотрите контекст, GGUF и инфраструктуру через [гайд запуска llama.cpp](/zhurnal/llama-cpp/) и [выбор видеокарты](/zhurnal/videokarta-dlya-llm/). Modelium эту тройку режимов на реальном оборудовании не запускал [s1](#src-s1)[s3](#src-s3)[s4](#src-s4).

## Источники

1. [llama.cpp — документация llama-server: типы KV, контекст, слоты и API](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/tools/server/README.md) — получено 2026-10-04
2. [llama.cpp — разбор CLI-флагов в common/arg.cpp](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/common/arg.cpp) — получено 2026-10-04
3. [llama.cpp — размещение тензоров и журнал KV-кеша в исходном коде](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/src/llama-kv-cache.cpp) — получено 2026-10-04
4. [llama.cpp — llama-bench: режимы и глубина контекста](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/tools/llama-bench/README.md) — получено 2026-10-04
5. [llama.cpp — сборка по исходникам и выбор backend](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/docs/build.md) — получено 2026-10-04
6. [llama.cpp — значения параметров cache_type_k и cache_type_v в common/common.h](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/common/common.h) — получено 2026-10-04
7. [llama.cpp — проверка Flash Attention для квантованного V в llama-context.cpp](https://github.com/ggml-org/llama.cpp/blob/0504396140d1c882f5f6ee34466a42db7ae90114/src/llama-context.cpp) — получено 2026-10-04
