Перейти к содержанию
Публикация AiManual

Как F16 KV-cache ускоряет Qwen 3.8 27B на двух Tesla P40 в llama.cpp

Разбираем, почему F16 KV-cache способен обогнать Q8 при запуске Qwen 3.8 27B на двух Tesla P40 в llama.cpp. В статье показаны связь с MTP и ngram-драфтом, роль

Коротко

Что будет в материале

  1. 01

    Короткий ответ: почему F16 KV-cache может обгонять Q8

  2. 02

    Тестовая конфигурация: две Tesla P40, Qwen 3.8 27B и llama.cpp

  3. 03

    Как F16 KV-cache связан с speculative decoding, MTP и ngram-драфтом

  4. 04

    Как корректно сравнить KV-cache Q8 и F16 в llama.cpp

F16 KV-cache может дать более высокую итоговую скорость генерации Qwen 3.8 27B на двух Tesla P40, хотя занимает больше памяти, чем Q8. Причина в том, что скорость зависит от стоимости операций с K и V, поведения GPU-пути и работы speculative decoding. В связке с MTP и ngram-драфтом ускорение появляется, когда выигрыш от более прямой обработки F16 перекрывает дополнительный объем чтения из VRAM.

Это не универсальное правило для всех видеокарт и сборок llama.cpp. В исходных данных нет журнала с фактическими tokens per second, acceptance rate, расходом памяти и задержками, поэтому конкретные числа ускорения нельзя подставлять без риска сфабриковать результат. Ниже приведен воспроизводимый профиль эксперимента и форма отчета, в которую нужно внести значения из собственных логов.

Для честного сравнения фиксируйте файл модели, квантизацию весов, commit llama.cpp, число GPU, параметры offload, контекст, batch, ubatch, MTP, ngram-драфт и промпты. Снимайте decode tokens per second, acceptance rate, задержку первого токена, расход VRAM и поведение кэша после заполнения длинного контекста.

Короткий ответ: почему F16 KV-cache может обгонять Q8

Что именно сравнивается: типы K и V, а не абстрактный «кэш»

В llama.cpp KV-cache состоит из двух частей: K, или keys, и V, или values. Тип данных для каждой части задается отдельно. Поэтому формулировка «используется Q8-кэш» недостаточно точна: в одном запуске могли применяться Q8 для K и V, а в другом один компонент мог остаться в F16.

РежимТип KТип VНазначение
Q8/Q8q8_0q8_0Базовый вариант с меньшим расходом памяти
F16/F16f16f16Вариант для проверки возможного выигрыша в скорости
Q8/F16q8_0f16Отдельный эксперимент с разными типами K и V
F16/Q8f16q8_0Отдельный эксперимент с обратным сочетанием

Названия значений нужно сверить с выводом llama-server --help и стартовыми логами конкретной сборки. Не переносите результат смешанного режима в выводы о F16/F16, пока не проведен отдельный прогон.

Почему меньший cache не обязан быть быстрее

Q8 сокращает объем данных, который нужно хранить в VRAM. Для длинного контекста это дает заметную экономию памяти и может позволить запустить больше токенов. Но квантизированные значения требуют специальной обработки при чтении и вычислениях. Ее стоимость зависит от реализации llama.cpp, выбранного GPU-пути, размера пакета и текущей нагрузки.

F16 расходует больше памяти, зато может лучше соответствовать операциям, которые выполняет конкретная сборка на Tesla P40. В этом случае уменьшается накладная работа при обращении к K и V, и итоговый decode ускоряется. Это рабочая техническая гипотеза, а не доказательство универсального преимущества F16.

При speculative decoding к стоимости чтения KV-cache добавляется проверка кандидатов. MTP и ngram-драфт предлагают несколько токенов, после чего основная модель проверяет их относительно накопленного контекста. Если проверка F16 проходит быстрее или принимает больше кандидатов, итоговая скорость растет. Если F16 приводит к нехватке памяти, выгрузке в RAM или сокращению контекста, преимущество исчезает.

Тестовая конфигурация: две Tesla P40, Qwen 3.8 27B и llama.cpp

Железо и распределение памяти

Исходный сценарий включает две Tesla P40 и модель Qwen 3.8 27B. Точный объем доступной VRAM каждой карты, системная RAM, процессор, ОС и способ соединения GPU в переданных данных не указаны. Эти поля нужно заполнить перед публикацией числового результата.

ПараметрЧто зафиксировать
GPU2 x Tesla P40
Доступная VRAM[укажите объем на GPU 0 и GPU 1 по мониторингу]
Системная RAM[укажите объем]
CPU[укажите модель и число потоков]
ОС и драйвер[укажите ОС, версию драйвера и CUDA-окружение]
Режим соединения GPU[укажите PCIe, наличие или отсутствие NVLink и номера устройств]
Фоновые процессы[укажите приложения, которые занимают VRAM или CPU]

Память расходуется на веса модели, KV-cache, входной контекст, промежуточные буферы и процессы операционной системы. При двух GPU нужно отдельно проверить распределение каждого ресурса. Формально помещающаяся модель может потерять скорость, если одному устройству не хватает запаса для KV-cache или рабочих буферов.

В отчете полезно записать свободную VRAM перед запуском, после загрузки весов, после создания KV-cache и во время длинной генерации. Если часть данных уходит в системную RAM, это нужно указать рядом с результатом. Связка двух карт не гарантирует одинаковое поведение при другой топологии PCIe или другом распределении слоев.

Практические вопросы распределения памяти для Qwen 3.8 27B на нескольких GPU разобраны в материале о локальном стеке Qwen 3.8 27B на двух RTX 3090. Аппаратные результаты оттуда нельзя переносить на Tesla P40, но подход к фиксации VRAM, RAM и draft-настроек применим.

Версия llama.cpp и файл модели

Общего названия Qwen 3.8 27B недостаточно для повторения эксперимента. Укажите точное имя GGUF-файла, квантизацию весов, размер файла, дату его получения и параметры chat template. В исходных данных эти значения отсутствуют, поэтому подставлять конкретный Q4, Q5 или другой вариант нельзя.

ПараметрПоле для отчета
Файл модели[точное_имя_файла.gguf]
Квантизация весов[например, значение из имени GGUF]
Размер модели на диске[укажите размер]
Сборка llama.cpp[commit или дата сборки]
Доступные cache-типы[вывод параметров cache-type-k и cache-type-v]
Chat template[значение из файла или параметров сервера]

Изменение файла весов или commit llama.cpp уже делает два прогона несопоставимыми с исходным результатом. Это особенно критично для speculative decoding: набор доступных параметров, формат логов и путь обработки draft-токенов могут меняться между сборками.

При выборе кванта полезно разделять вопрос о весах и вопрос о KV-cache. Веса модели остаются одинаковыми в паре Q8/F16-прогонов, меняются только типы K и V. Практический разбор запуска Qwen3.8-27B в true Q4_K_M с ограниченной VRAM приведен в статье о Q4_K_M, VRAM и длинном контексте.

Профиль серверного запуска

Ниже приведен каркас команды. Значения в квадратных скобках нужно заменить параметрами конкретной системы. Строки для MTP и ngram-драфта намеренно обозначены полями: без версии бинарника нельзя гарантировать точные имена этих опций.

llama-server -m /path/to/[точное_имя_файла.gguf] -c [CTX] -b 4096 -ub 4096 -ngl [LAYERS] -t 8 --cache-type-k q8_0 --cache-type-v q8_0 [MTP_ARGS] [NGRAM_ARGS]

Параметры -b 4096 и -ub 4096 можно взять как отправную точку для отдельного профиля. В одном из описанных домашних сценариев использовался лимит -t 8, поскольку скорость decode упиралась в пропускную способность памяти. Для двух Tesla P40 это поле нужно измерить заново: большее число CPU-потоков не гарантирует прирост.

Для второго прогона замените только значения --cache-type-k и --cache-type-v:

llama-server -m /path/to/[точное_имя_файла.gguf] -c [CTX] -b 4096 -ub 4096 -ngl [LAYERS] -t 8 --cache-type-k f16 --cache-type-v f16 [MTP_ARGS] [NGRAM_ARGS]

Число слоев GPU-offload, распределение между устройствами, размер контекста, batch, ubatch и draft-параметры должны совпадать. В логах проверьте фактическую загрузку слоев, типы K/V, объем выделенной памяти и отсутствие fallback в RAM.

Как F16 KV-cache связан с speculative decoding, MTP и ngram-драфтом

Что меняют MTP и ngram-драфт

Обычный decode генерирует один следующий токен после обработки текущего состояния модели. Speculative decoding меняет последовательность: draft-механизм предлагает несколько будущих токенов, а основная модель проверяет их одним шагом или короткой серией операций.

MTP, или multi-token prediction, использует дополнительный механизм модели для предложения нескольких будущих токенов. Ngram-драфт строит кандидатов по последовательностям, которые уже встречались в контексте. Эти методы имеют разную природу и могут показывать разный acceptance rate на коде, диалоге, повторяющихся инструкциях и свободном тексте.

Доступность MTP и ngram-драфта, число кандидатов и точные флаги зависят от конкретной сборки llama.cpp. Поэтому в статье или отчете нужно привести строку запуска и фрагмент стартового лога, а не ограничиваться словами «спекулятивное декодирование включено».

В отдельном разборе Qwen 3.8 27B на RTX 5090 описана связь MTP, int8 KV-cache, prefill и decode. Эти наблюдения полезны как методический ориентир, но не заменяют измерение на Tesla P40: сравнение локального запуска Qwen на одной RTX 5090.

Acceptance rate важнее одной цифры tokens per second

Acceptance rate показывает долю предложенных draft-токенов, которые основная модель приняла. Базовая формула выглядит так: acceptance rate = принятые draft-токены / предложенные draft-токены.

Например, если draft предложил 4 токена, а модель приняла 3, acceptance rate равен 75 процентов. Это учебный пример, не результат запуска Qwen 3.8 27B на Tesla P40.

МетрикаЗачем нужна
Decode, токенов в секундуПоказывает итоговую скорость выдачи
Acceptance rateПоказывает, насколько часто основная модель принимает предложения draft-механизма
Принятые токены за шагПомогает понять реальный выигрыш speculative decoding
Задержка первого токенаОтделяет стоимость prefill и подготовки запроса от скорости дальнейшей генерации
Средняя задержка токенаПоказывает поведение системы в рабочем сценарии

Высокая скорость draft-механизма сама по себе мало говорит о результате. Если acceptance rate низкий, основная модель часто отклоняет кандидатов, и стоимость их проверки может съесть выигрыш. При сравнении F16 и Q8 записывайте все эти значения для одного и того же промпта.

Где в цепочке появляется стоимость KV-cache

На каждом шаге основная модель обращается к накопленным K и V, чтобы учитывать предыдущий контекст. При speculative decoding она проверяет несколько предложенных продолжений, поэтому стоимость доступа к кэшу входит в цену проверки кандидатов.

Q8 сокращает размер хранения, но требует обработки квантизированных данных. F16 увеличивает объем KV-cache, зато конкретный путь вычислений может работать с меньшей дополнительной обработкой. На итог влияют длина контекста, batch, ubatch, layout тензоров, межGPU-обмен и наличие свободной памяти.

Связь между F16 и ростом acceptance rate нельзя объявлять доказанной без логов. Сам тип хранения K/V не обязан менять вероятности модели, однако нехватка памяти, изменение профиля запуска или fallback в RAM меняют время проверки и итоговое поведение сервера. Профилирование должно отделить влияние cache-типа от остальных факторов.

Как корректно сравнить KV-cache Q8 и F16 в llama.cpp

Какие условия должны быть одинаковыми

Сравнение строится серией контролируемых прогонов. Между Q8 и F16 меняются только типы K и V. Если одновременно меняются batch, контекст или draft-механизм, результат показывает сумму нескольких изменений.

  • Один и тот же файл GGUF и одна квантизация весов.
  • Один commit или одна дата сборки llama.cpp.
  • Две Tesla P40 с тем же порядком устройств и тем же распределением слоев.
  • Один размер контекста, batch, ubatch и число CPU-потоков.
  • Одинаковые MTP, ngram-драфт, число предлагаемых токенов и chat template.
  • Одинаковые промпты, seed или правила формирования запросов.
  • Одинаковое число повторов и одинаковый прогрев.
  • Остановленные фоновые процессы, которые могут занять VRAM или CPU.

Перед каждым прогоном запускайте чистый процесс сервера. Состояние KV-cache после предыдущего запроса может влиять на время и доступную память. Смешивание измерений с рабочими запросами дает шумный результат.

Какие метрики снять из логов

Минимальный отчет должен разделять prefill и decode. Prefill показывает скорость обработки входного контекста, decode описывает генерацию ответа. Для длинных запросов эти показатели ведут себя по-разному.

РежимКонтекстPrefillDecodeAcceptance rateVRAMRAMЗадержка первого токена
Q8/Q8[короткий][значение][значение][значение][значение][значение][значение]
F16/F16[короткий][значение][значение][значение][значение][значение][значение]
Q8/Q8[длинный][значение][значение][значение][значение][значение][значение]
F16/F16[длинный][значение][значение][значение][значение][значение][значение]

Записывайте минимум три повтора для каждого состояния и указывайте среднее значение вместе с разбросом. Единичный пик в tokens per second не доказывает устойчивое ускорение. Отдельно отметьте падение decode к концу длинного контекста, ошибки выделения памяти, fallback в RAM и внезапное снижение acceptance rate.

Как использовать стресс-тест KV-cache

Параметр максимального контекста описывает доступный режим запуска. Он не доказывает, что система удержит весь вычисленный контекст без вытеснения старых записей. Реальную емкость нужно проверять по тому, сколько ранее добавленных контекстов модель продолжает распознавать после последовательного заполнения кэша.

Практический протокол выглядит так:

  1. Запустите отдельный чистый сервер и выполните калибровочный запрос, чтобы проверить формат ответа и стабильность измерения.
  2. Последовательно добавляйте различимые стабильные контексты. Каждому фрагменту присвойте уникальный маркер, который можно проверить позднее.
  3. Создайте давление новыми контекстами, постепенно приближаясь к рабочему лимиту.
  4. Повторно запросите старые маркеры в прежней последовательности.
  5. Зафиксируйте, какие записи распознаны, где появилась первая потеря и как изменилась скорость.

В отчете используйте метрики retained tokens, retained % capacity и oldest evicted. Повторите протокол для Q8/Q8 и F16/F16 при одинаковом размере контекста.

Стресс-тест меняет состояние текущего KV-cache, поэтому его нельзя запускать рядом с рабочими запросами. Используйте отдельный остановленный сервер или изолированный процесс. Результат относится к конкретной связке модели, квантизации весов, GPU, версии llama.cpp, параметров запуска, длины тестовых контекстов и фоновой нагрузки.

Почему на длинном контексте картина меняется

Заявленный контекст против реально удерживаемого кэша

Большой параметр контекстного окна означает, что сервер способен принять такой режим запуска. Фактическое удержание ранее вычисленных данных зависит от бюджета памяти и поведения KV-cache. При давлении старые записи могут вытесняться, а часть ресурсов может уйти в системную RAM.

Проверяйте это через уникальные маркеры и повторные запросы. Если старый маркер исчез после добавления новых данных, заявленный лимит контекста нельзя считать фактической емкостью удерживаемого кэша. В отчете указывайте момент первой потери и значение oldest evicted.

Методика проверки емкости применима к разным inference-движкам, включая llama.cpp, vLLM и SGLang, если протокол и условия совпадают. Внутренние форматы кэша у них различаются, поэтому сравнивать нужно измеренное поведение, а не цифры конфигурации.

Как контекст влияет на скорость decode и acceptance rate

На коротком контексте F16 может показать преимущество за счет особенностей обработки K/V. После заполнения значительной части окна объем обращений к KV-cache растет, свободный запас памяти сокращается, а межGPU-обмен и рабочие буферы получают больше влияния на итоговую скорость.

СценарийЧто измерятьЧто искать в логах
Короткий контекстPrefill, decode, acceptance rateПреимущество F16 сразу после прогрева
Средний контекстТе же метрики после накопления данныхИзменение задержки и числа принятых токенов
Длинный контекстDecode по этапам, VRAM, RAM, retained tokensПадение скорости, вытеснение записей или fallback

Для практического прогона можно выбрать три заранее заданных уровня, например короткий, средний и длинный, и не менять их между Q8 и F16. Значения контекста следует подобрать под фактический бюджет памяти. Материалы о KV-квантах и поведении длинного контекста в форке beellama показывают, почему заявленное ускорение нужно подтверждать отдельными замерами: разбор KLD, логитов и KV-квантов.

В домашнем инференсе prefill может достигать сотен токенов в секунду, а decode может превышать 10 токенов в секунду, но эти числа относятся к отдельному примеру и не описывают две Tesla P40 с Qwen 3.8 27B. К концу длинного контекста decode обычно снижается, поэтому короткий прогон не заменяет длительный стресс-тест.

Память GPU, системная RAM и промежуточные буферы

Общий бюджет памяти складывается из нескольких частей. Веса модели занимают базовый объем. KV-cache растет вместе с контекстом. Входные токены и batch требуют рабочих буферов, а операционная система и сервер могут оставлять собственный резерв.

Параметры -b и -ub влияют на prefill, размеры временных буферов и расход памяти. При двух Tesla P40 проверяйте каждую карту отдельно: одна может иметь свободный запас, а другая уже работать на границе. Не считайте запуск полностью GPU-based, если часть слоев или KV-cache ушла в RAM.

Для диагностики полезно сохранить снимки мониторинга до запуска, после загрузки модели и во время длинного запроса. Зафиксируйте температуру, загрузку GPU, занятую VRAM, системную RAM и признаки обмена через PCIe. Эти данные помогают отличить влияние F16 от последствий нехватки памяти.

Практическая настройка F16 KV-cache в серверном профиле llama.cpp

Параметры cache type для K и V

В серверном профиле типы кэша задаются отдельно:

--cache-type-k q8_0 --cache-type-v q8_0

Для F16/F16 используется:

--cache-type-k f16 --cache-type-v f16

Сверяйте синтаксис с помощью конкретного бинарника. После запуска найдите в логах строки, которые подтверждают тип K, тип V, размер KV-cache и место его размещения. Строка команды показывает намерение пользователя, а лог показывает фактический режим.

Для смешанных вариантов используйте отдельные команды:

--cache-type-k q8_0 --cache-type-v f16

Такой прогон помогает понять, какой компонент влияет на скорость, однако его нельзя объединять с выводом о полном F16-кэше. Для каждого сочетания нужны собственные показатели памяти, decode и acceptance rate.

Batch и ubatch как часть конкретного профиля

В одном описанном профиле применялись -b 4096 и -ub 4096. Эти значения можно проверить как стартовую точку, но универсальным рецептом они не служат. Большой batch способен ускорить обработку входного контекста и одновременно увеличить потребление памяти.

Меняйте batch и ubatch отдельным экспериментом. При сравнении Q8 и F16 оставляйте их одинаковыми, иначе рост скорости нельзя будет связать с типом KV-cache. Если F16 требует уменьшить batch, это часть практической цены режима и должна попасть в итоговую таблицу.

Для длинного контекста отдельно проверяйте момент, когда свободная VRAM заканчивается. В этот момент скорость может измениться резче, чем после обычной смены cache-типа. Такой переход нужно пометить в логах и не смешивать с результатами стабильного режима.

Проверка GPU offload и состояния сервера

Полный GPU offload означает, что все слои, которые вы планировали разместить на видеокартах, действительно загружены туда. В команде это обычно связано с параметром -ngl, но точное число слоев и схема распределения зависят от файла модели и версии llama.cpp.

Перед тестом проверьте:

  • какие GPU обнаружил сервер;
  • сколько слоев загружено на каждую Tesla P40;
  • где размещен KV-cache;
  • какой объем VRAM занят после загрузки;
  • есть ли сообщения о fallback в RAM или нехватке памяти;
  • совпадают ли параметры Q8 и F16 в стартовом логе.

После смены cache-типа завершите старый процесс и запустите новый. Очистка состояния нужна для сопоставимого prefill и одинакового начального бюджета памяти. Не проводите стресс-тест на сервере, который обслуживает пользователей.

Как интерпретировать результат и выбрать режим

Минимальная таблица сравнения Q8 и F16

Финальный отчет должен показывать цену скорости. Одной колонки decode недостаточно: F16 может ускорить короткие ответы, но сократить доступный контекст или вызвать нехватку VRAM на длинном запросе.

Типы K/VКонтекстPrefillDecodeAcceptance rateПринятые токеныVRAMRAMTTFTСтабильностьПримечание
Q8/Q8[короткий][ ][ ][ ][ ][ ][ ][ ][ ][ ]
F16/F16[короткий][ ][ ][ ][ ][ ][ ][ ][ ][ ]
Q8/Q8[длинный][ ][ ][ ][ ][ ][ ][ ][ ][ ]
F16/F16[длинный][ ][ ][ ][ ][ ][ ][ ][ ][ ]

Заполняйте таблицу после одинакового прогрева и нескольких повторов. В поле стабильности отмечайте ошибки, зависания, fallback, резкое падение скорости и потерю старых записей KV-cache. Для рабочих запросов полезнее устойчивое ускорение на длинном контексте, чем разовый максимум на коротком промпте.

Когда результат нельзя обобщать

Вывод о F16 относится к конкретной связке: две Tesla P40, конкретный файл Qwen 3.8 27B, квантизация весов, версия llama.cpp, параметры GPU-offload, batch, ubatch, MTP, ngram-драфта и выбранные контексты.

Результат изменится после замены GPU, драйвера, файла GGUF, chat template или режима распределения слоев. На другой системе F16 может дать меньший выигрыш, не изменить decode или оказаться непрактичным из-за расхода VRAM. Q8 может выигрывать при большем контексте, нескольких параллельных запросах или ограниченном запасе памяти.

Сравнение с другими локальными системами требует такого же протокола. Разбор Qwen3.8-Flash-Next показывает, как VRAM, RAM, mmap и способ размещения KV влияют на скорость при длинном контексте: материал о поведении Qwen3.8-Flash-Next в llama.cpp. Его цифры нельзя использовать как бенчмарк Tesla P40.

Короткий алгоритм для собственного запуска

  1. Запишите точные GPU, доступную VRAM, RAM, CPU, ОС, драйвер и режим соединения карт.
  2. Зафиксируйте имя GGUF-файла, квантизацию весов, commit llama.cpp и chat template.
  3. Запустите чистый сервер с Q8/Q8 и сохраните стартовый лог.
  4. Проверьте GPU-offload, расположение KV-cache и отсутствие fallback в RAM.
  5. Снимите prefill, decode, acceptance rate, число принятых токенов, TTFT, RAM и VRAM.
  6. Повторите тот же сценарий с F16/F16, изменив только --cache-type-k и --cache-type-v.
  7. Проверьте короткий, средний и длинный контекст при одинаковых настройках speculative decoding.
  8. Запустите изолированный стресс-тест и измерьте retained tokens, retained % capacity и oldest evicted.
  9. Сравните итоговый decode с acceptance rate, задержкой и расходом памяти.
  10. Выберите F16, если прирост устойчив в нужном рабочем сценарии и сохраняется запас VRAM. Оставьте Q8, если экономия памяти важнее или ускорение не повторяется.

F16 KV-cache стоит проверять на двух Tesla P40 именно как часть связки с Qwen 3.8 27B, llama.cpp, MTP и ngram-драфтом. Больший объем хранения может окупиться более дешевой обработкой K/V и лучшей итоговой скоростью проверки кандидатов. Q8 остается рациональным выбором при ограниченной памяти, большем контексте и отсутствии подтвержденного ускорения F16. Решение принимает таблица замеров, а не размер кэша сам по себе.

Подписаться на канал