Хардкорный NIAH или почему у Gemma 26B память рыбки, какой Qwen лучше, и что показали 8 моделей на RTX 5090
Привет, Хабр.
Меня зовут Артём Хакимов, я работаю в команде GPUGO.
Большая часть наших пользователей, которая не создаёт ИИ-подружек, работает с LLM — кто-то дообучает, кто-то гоняет инференс. И у всех одни и те же вопросы: «что быстрее?», «сколько контекста влезет?», «какой квант брать?».
В какой-то момент надоело отвечать «зависит от…» — сел и прогнал всё сам. Собрал стенд, взял 8 конфигураций моделей, погонял llama-bench на контекстах от 4K до 256K. Но скорость — это половина дела: модель может влезать в 128K и генерировать 200 tok/s, а на деле не найти нужный факт в тексте. Поэтому написал свой NIAH-бенчмарк — не классический «найди одну иголку», а с тройным хопом и пятью дистракторами-ловушками. Подробнее о нём расскажу ниже, пара результатов заставила перепроверить скрипт дважды.
Спойлер: Qwen3.6-27B Dense набрал 98% на NIAH до 128K, обогнав собственную MoE-версию на 35B (что неудивительно, если вы в теме). А Gemma 4, которая идеально работает на коротких контекстах, почему-то на 64K полностью разваливается — 0 из 10.
Что тестируем и зачем
Задача простая: понять, какую модель поставить на RTX 5090 с 32 ГБ VRAM для повседневного инференса. Не абстрактно «лучшую по бенчмаркам Artificial Analysis», а конкретно — что быстрее генерирует, что влезает в память, и что не теряет голову на длинных контекстах.
Мне были интересны три вещи. Во-первых, сырая скорость: сколько токенов в секунду на prompt processing и на генерации. Во-вторых, потолок контекста: на каком размере KV-кэш перестаёт влезать в 32 ГБ. И в-третьих, качество длинного контекста: одно дело влезть в память, другое — реально найти нужную информацию в 128K токенов.
Стенд
Все замеры сделаны на инфраструктуре GPUGO.
-
GPU: NVIDIA RTX 5090, 32 ГБ GDDR7 (Blackwell)
-
CPU: 24 vCPU, 55 ГБ RAM
-
Хранилище: 474 ГБ ADATA LEGEND 960 NVMe
-
Инференс-движок: llama.cpp (сборка b9128, CUDA arch sm_120)
-
Бенчмарк скорости:
llama-benchс flash attention, batch 2048, ubatch 512 -
Бенчмарк качества: собственный NIAH v3 (triple-hop + 5 distractors)
-
Кванты: Q4_K_M и UD-Q4_K_XL от Unsloth
Участники
Восемь конфигураций — пять моделей в двух квантах:
|
Модель |
Архитектура |
Параметры |
Активные |
Квант |
|---|---|---|---|---|
|
Qwen3.6-35B-A3B |
MoE |
35B |
3B |
Q4_K_M |
|
Qwen3.6-27B |
Dense |
27B |
27B |
Q4_K_M |
|
Qwen3.6-27B |
Dense |
27B |
27B |
UD-Q4_K_XL |
|
Gemma 4 26B-A4B |
MoE |
26B |
4B |
UD-Q4_K_XL |
|
Gemma 4 26B-A4B |
MoE |
26B |
4B |
UD-Q4_K_M |
|
Mistral Small 3.1 24B |
Dense |
24B |
24B |
Q4_K_M |
|
Mistral Small 3.1 24B |
Dense |
24B |
24B |
UD-Q4_K_XL |
|
Devstral Small 2 24B |
Dense |
24B |
24B |
Q4_K_M |
|
Devstral Small 2 24B |
Dense |
24B |
24B |
UD-Q4_K_XL |
Devstral — это файнтюн Mistral Small 3.1 под код и инструкции. Архитектура та же, веса другие. Интересно посмотреть, что это меняет.
DeepSeek-R1-Distill-Qwen-32B тоже участвовал, но на текущем стенде показал ~6 tok/s на генерации и зависания на 16K — в итоговую таблицу не попал. В принципе вот и все, можем приступать.
Часть 1. Скорость: llama-bench
Методика: llama-bench с --flash-attn 1, prompt processing на 4K/16K/32K токенов, генерация 256 токенов. По 1–3 повтора на каждый замер. Знаю, знаю — llama-bench прогнал уже каждый второй автор на Хабре, и вы наверняка видели эти таблицы сто раз. Но хочется иметь честные цифры с одного стенда, одного билда llama.cpp, в одинаковых условиях для всех моделей, иначе сравнивать бессмысленно.
MoE: Qwen3.6-35B-A3B и Gemma 4
Небольшая техническая справка, чтобы дальше все были на одной волне. MoE-модели устроены хитро: параметров в них десятки миллиардов, но при генерации каждого токена работает только маленькая часть, так называемые «активные эксперты». У Qwen это 3B из 35B, у Gemma 4B из 26B. Остальные просто лежат в памяти и ждут своей очереди. Поэтому decode у MoE летит: GPU считает мало, а результат на уровне большой модели (почти).
|
Модель |
PP 4K |
PP 16K |
PP 32K |
PP 128K |
TG 256 |
VRAM 32K |
|---|---|---|---|---|---|---|
|
Qwen3.6-35B-A3B Q4_K_M |
9 085 |
8 647 |
8 171 |
5 735 |
274.8 |
21.8 ГБ |
|
Gemma 4 UD-Q4_K_XL |
12 300 |
11 362 |
10 175 |
5 465 |
222.5 |
18.3 ГБ |
|
Gemma 4 UD-Q4_K_M |
12 360 |
11 399 |
10 189 |
5 449 |
223.1 |
18.3 ГБ |
Главное из таблицы: Qwen чемпион по decode (~275 tok/s), Gemma по prompt processing (~12 300 tok/s на 4K). Логично: у Qwen меньше активных параметров (3B vs 4B), поэтому генерация быстрее. Gemma эффективнее обрабатывает входной текст, на коротких промптах она в полтора раза быстрее Qwen.
Тут интересный момент — 275 tok/s на генерации это примерно 4 слова в секунду на русском, то есть текст появляется быстрее, чем большинство людей успевает читать. Возникает вопрос: а нужно ли вообще гнаться за скоростью decode дальше этой отметки? Наверное, для чатбота уже нет. А вот для API, где параллельно висят несколько запросов, каждый лишний tok/s экономит какие-никакие деньги.
На практике это определяет сценарий использования. Чатбот, стриминг ответа, интерактивный помощник? Decode важнее, Qwen выигрывает. Быстро переварить длинный документ и выдать короткое резюме? PP важнее, Gemma впереди.
Ещё один плюс Gemma: экономность по памяти. 18 ГБ VRAM на 32K контексте против 22 ГБ у Qwen. Благодаря этому она влезает в 256K контекст при 23 ГБ, самый длинный рабочий контекст на нашем стенде. Правда, как покажет NIAH дальше, «влезть» и «работать» это разные вещи.
Между двумя квантами Gemma (UD-Q4_K_XL и UD-Q4_K_M) разница в пределах шума, можно брать любой.
Dense: Qwen3.6-27B, Mistral Small 3.1, Devstral Small 2
Ещё одна техническая справка. Dense-модели устроены проще: никаких экспертов, все параметры работают на каждый токен. Это обычно даёт лучшее качество на единицу параметров, но за это приходится платить скоростью. GPU вынужден прочитать все 24–27 миллиардов весов для каждого нового токена, и decode почти всегда упирается в пропускную способность памяти.
|
Модель |
PP 4K |
PP 16K |
PP 32K |
TG 256 |
VRAM 32K |
|---|---|---|---|---|---|
|
Qwen3.6-27B Q4_K_M |
3 804 |
3 531 |
3 169 |
76.5 |
18.7 ГБ |
|
Qwen3.6-27B UD-Q4_K_XL |
3 742 |
3 482 |
3 151 |
73.8 |
19.5 ГБ |
|
Mistral Small 3.1 Q4_K_M |
4 817 |
4 343 |
3 809 |
101.5 |
19.3 ГБ |
|
Mistral Small 3.1 UD-Q4_K_XL |
4 967 |
4 413 |
3 824 |
100.6 |
19.5 ГБ |
|
Devstral Small 2 Q4_K_M |
5 035 |
4 459 |
3 836 |
96.9 |
19.3 ГБ |
|
Devstral Small 2 UD-Q4_K_XL |
5 059 |
4 474 |
3 845 |
96.1 |
19.5 ГБ |
Тут всё предсказуемо. Mistral и Devstral близнецы по скорости (~100 tok/s), потому что Devstral это файнтюн Mistral на том же скелете. Qwen3.6-27B медленнее (~76 tok/s) просто потому что тяжелее: 27B против 24B, больше весов читать на каждый токен.
А вот что првда порадовало: Q4_K_M и UD-Q4_K_XL дают одинаковую скорость на всех Dense-моделях. Разница 1–3%, статистический шум. UD-квант чуть тяжелее по памяти (на 100–750 МБ), но по скорости полный паритет. Ребята из Unsloth сделали крутую работу и их динамическая квантизация даёт лучшее качество весов, и при этом не просаживает скорость. Однозначная доминация во всех смыслах, берем UD-квант и не думаем о компромисах.
256K — потолок
Обе MoE-модели влезли в 256K на 32 ГБ VRAM, но с ньюансами. Gemma экономнее: 23.1 ГБ против 26.6 ГБ у Qwen. У Qwen на 256K остаётся всего ~5 ГБ запаса, так что в реальном сценарии с системным промптом и длинной генерацией можно и упереться.
|
Модель |
Контекст |
PP tok/s |
TG tok/s |
VRAM |
|---|---|---|---|---|
|
Gemma 4 UD-Q4_K_XL |
128K |
5 465 |
222.7 |
20.3 ГБ |
|
Gemma 4 UD-Q4_K_XL |
256K |
3 454 |
223.5 |
23.1 ГБ |
|
Qwen3.6-35B-A3B Q4_K_M |
128K |
5 735 |
273.1 |
23.7 ГБ |
|
Qwen3.6-35B-A3B Q4_K_M |
256K |
3 980 |
272.3 |
26.6 ГБ |
Интересное наблюдение: decode практически не деградирует от длины контекста. Обе модели на 256K генерируют с той же скоростью, что и на 4K, как будто им всё равно, сколько текста было до этого. Просадка идёт только в prompt processing: переварить 256K входного текста занимает в ~3.5 раза больше времени, чем 4K. Это ожидаемо, PP линейно зависит от длины промпта.
Mistral и Devstral в этот клуб не попали: при 128K KV-кэш вместе с весами перестаёт влезать в 32 ГБ. Их потолок 64K.
Часть 2. Качество длинного контекста: NIAH v3
Скорость это полдела. Модель может влезать в 128K и генерировать 200 tok/s, но если она не может найти нужный факт в тексте, толку от этого мало. А сценариев, где это критично, полно: суммаризация длинных документов, code review на тысячи строк, RAG по корпоративной базе знаний, анализ логов. Везде, где модель должна не просто принять длинный вход, а реально в нём разобраться.
Классический способ это проверить называется Needle In A Haystack (NIAH). Идея простая: прячем факт («иголку») в длинный текст («стог сена») и спрашиваем модель, может ли она его найти. Тест появился пару лет назад и быстро стал стандартом для оценки длинного контекста. Проблема в том, что стандартный NIAH сегодня слишком прост. Одна иголка, один стог, прямой вопрос. Все современные модели щёлкают его на 100%.
Поэтому я написал свой вариант, NIAH v3: три связанных факта (тройной хоп) и пять дистракторов-ловушек, специально сконструированных чтобы сбить модель с толку.
Как устроен тест
Три факта образуют цепочку, которую нужно восстановить:
-
Fact A (фиксирован на ~10% документа): «Employee ID E-4821 is the project lead for the Orion initiative.»
-
Fact B (перемещается от 5% до 95% — это ось X на тепловых картах): «The Orion initiative is supervised by Division DELTA-9.»
-
Fact C (фиксирован на ~85%): «Division DELTA-9 has an annual operational budget of $2.4 million.»
Чтобы ответить правильно, модель должна пройти три хопа: E-4821 → Orion → DELTA-9 → $2.4M. Но это ещё не всё. В документ вшиты пять дистракторов — ложные факты, специально сконструированные чтобы сбить модель:
-
Ложный сотрудник E-4822 ведёт проект Titan (не Orion)
-
Titan контролируется дивизионом GAMMA-7 (не DELTA-9)
-
У GAMMA-7 бюджет $3.7M (главная ловушка — та же структура фразы, что и правильный ответ)
-
У Orion есть supplemental funding $5.1M (правильная сущность, неправильный тип бюджета)
-
У DELTA-9 есть capital expenditure reserve $8.6M (правильный дивизион, неправильный тип бюджета)
Вопрос: «What is the annual operational budget of the division that supervises the project led by employee E-4821?»
Правильный ответ: $2.4 million. Все остальные числа — ловушки.
Тест прогоняется на контекстах 4K / 8K / 16K / 32K / 64K / 128K, по 10 позиций Fact B на каждом. Итого 60 запросов на модель (или 50 для Mistral/Devstral, у которых 128K не влезает).
Результаты
|
Модель |
4K |
8K |
16K |
32K |
64K |
128K |
Итого |
|---|---|---|---|---|---|---|---|
|
Qwen3.6-27B Q4_K_M |
10/10 |
10/10 |
10/10 |
10/10 |
10/10 |
9/10 |
98% |
|
Qwen3.6-27B UD-Q4_K_XL |
10/10 |
10/10 |
10/10 |
10/10 |
10/10 |
9/10 |
98% |
|
Devstral-Small-2 UD-Q4_K_XL |
8/10 |
10/10 |
9/10 |
9/10 |
6/10 |
— |
84% |
|
Qwen3.6-35B-A3B Q4_K_M |
9/10 |
10/10 |
6/10 |
10/10 |
9/10 |
5/10 |
82% |
|
Devstral-Small-2 Q4_K_M |
8/10 |
9/10 |
9/10 |
9/10 |
5/10 |
— |
80% |
|
Mistral-Small-3.1 UD-Q4_K_XL |
7/10 |
8/10 |
10/10 |
3/10 |
2/10 |
— |
60% |
|
Mistral-Small-3.1 Q4_K_M |
6/10 |
8/10 |
9/10 |
2/10 |
2/10 |
— |
54% |
|
Gemma4-26B UD-Q4_K_XL |
10/10 |
10/10 |
6/10 |
4/10 |
0/10 |
0/10 |
50% |

Тепловые карты NIAH v3 по всем моделям

Recall vs Context Length — все модели
Что тут произошло
Qwen3.6-27B набрал 98% на всём диапазоне, включая 128K. Из 60 запросов ошибся ровно один раз, на 128K при глубине 55%. Посмотрите на тепловую карту: сплошной зелёный ковёр с одним красным пикселем. Для Dense-модели на Q4 кванте это выдающийся результат. Мы специально прогнали оба кванта (Q4_K_M и UD-Q4_K_XL) и получили одинаковые 98%. Это значит, что рассуждение у модели не ломается от квантования: цепочка «найти сотрудника → определить проект → найти дивизион → вытащить бюджет» работает одинаково надёжно в обоих случаях. Для практики это важно: можно смело квантовать и не бояться и в RAG сценариях.

NIAH: Qwen3.6-27B Q4_K_M
Qwen3.6-35B-A3B — нестабилен. 82% — это хуже, чем у его Dense-собрата на 27B. MoE-версия проваливается на 16K (6/10) и на 128K (5/10), хотя на 32K и 64K восстанавливается. Видно, что при определённых позициях иголки в середине документа MoE-роутинг теряет нить рассуждений.

NIAH: Qwen3.6-35B-A3B Q4_K_M
Gemma 4 — поразительная деградация. На 4K и 8K — идеально, 10/10. На 16K начинается провал. На 64K и 128K — ноль из десяти. Абсолютный ноль. При этом по скорости Gemma прекрасно работает на 128K и даже на 256K. Но толку нет: карта зелёная на коротких контекстах и сплошь красная на длинных.

NIAH: Gemma4-26B UD-Q4_K_XL
Что именно идёт не так? Модели ловятся на дистракторы. Вместо правильных $2.4M они отвечают $3.7M (пошли по ложной цепочке E-4822 → Titan → GAMMA-7) или $8.6M (нашли правильный дивизион DELTA-9, но схватили capital expenditure вместо operational budget). И что характерно, отвечают уверенно, в правильном формате, без оговорок. Просто с неправильным числом. Модель не «сломалась», она честно рассуждала, но по неправильным фактам. Это самый коварный тип ошибки: на вид всё выглядит убедительно, и без проверки вы бы не заметили.
Отдельно интересно сравнение Devstral и Mistral. Одна архитектура, одинаковый размер, одинаковая скорость в llama-bench. Но Devstral набрал 80–84%, а Mistral 54–60%. Откуда разница? Devstral это файнтюн Mistral Small 3.1, который в Mistral AI дообучали специально под агентные задачи. По их статье, процесс выглядел так: сначала SFT на синтетических агентных траекториях (модель учится работать с bash, редактировать файлы, следовать многошаговым инструкциям), потом дополнительные раунды оптимизации политики с повторными прогонами. Плюс обучение на нескольких форматах взаимодействия (XML и нативный function calling), чтобы модель не привязывалась к одному формату. Результат виден на тепловых картах: Devstral ровнее держит точность по всему диапазону контекстов, Mistral начинает сыпаться с 32K. Агентный файнтюн, похоже, научил модель аккуратнее следить за цепочкой рассуждений, и это помогает не только в коде.

NIAH: Devstral-Small-2 UD-Q4_K_XL

NIAH: Mistral-Small-3.1 Q4_K_M
Часть 3. Q4_K_M vs UD-Q4_K_XL — есть ли разница?
Один из частых вопросов: стоит ли брать динамический квант UD-Q4_K_XL от Unsloth вместо стандартного Q4_K_M?
По скорости разницы нет. Вообще. Ни на одной модели decode не изменился значимо. Prompt processing тоже в пределах шума. VRAM чуть выше, на 100–750 МБ.
По качеству NIAH тоже нет разницы: оба кванта Qwen3.6-27B набрали 98%, оба кванта Mistral около 55–60%, оба кванта Devstral 80–84%.
Честно говоря, я ожидал увидеть хоть какой-то разрыв. Не увидел. Но тут важно понимать: наш NIAH проверяет retrieval и многошаговое рассуждение, а не тонкости генерации. Вполне возможно, что разница между квантами вылезет на задачах, где важна точность формулировок: сложная математика, генерация кода, нюансы перевода. Там perplexity решает, и UD-Q4_K_XL теоретически должен быть ближе к оригиналу. Но для этого нужен другой бенчмарк, и это тема для отдельного поста.
Часть 4. MTP — Multi-Token Prediction
Обычная генерация работает так: один проход через модель — один токен. MTP (Multi-Token Prediction) меняет правила: модель обучена предсказывать сразу несколько следующих токенов за один проход. Qwen3.6 обучена с 3 шагами MTP — значит, каждый проход пытается выдать 4 токена. Если «черновики» совпали с тем, что модель выдала бы обычным способом — получаем 4 токена за цену одного. Если нет — откатываемся. Чем выше acceptance rate, тем больше выигрыш.
В основной ветке llama.cpp MTP пока не поддерживается. Мы собирали из открытого PR #22673. MTP-слои весят мало (Q8_0, крошечная часть модели) и почти не добавляют VRAM. Главный вопрос — насколько это ускоряет генерацию на практике.
Наши замеры
|
Модель |
Режим |
Prompt t/s |
Gen t/s |
|---|---|---|---|
|
Qwen3.6-35B-A3B |
без MTP |
251.5 |
236.1 |
|
Qwen3.6-35B-A3B |
draft-mtp |
196.2 |
197.6 |
|
Qwen3.6-27B |
без MTP |
241.9 |
73.0 |
|
Qwen3.6-27B |
draft-mtp, n_max=3 |
208.3 |
92.6 |
На MoE-модели (35B-A3B) MTP навредил. MoE и так летит на decode за счёт малого числа активных параметров, и overhead от спекуляции съедает весь выигрыш. Модель тратит время на проверку черновиков, которые ей не нужны.
На Dense-модели (27B) мы получили +27%, с 73 до 92.6 tok/s. Неплохо, но далеко от теоретических 2–3x. Наш тест был коротким smoke-замером: один промпт, ~220 токенов генерации. На коротких ответах acceptance rate нестабилен, MTP просто не успевает раскрыться.
В комьюнити результаты интереснее. Пользователь на Reddit собрал GGUF Qwen3.6-27B с прикрученными MTP-слоями (UD-Q4_K_XL база + Q8 MTP) и получил ~2.08x ускорение на наборе из 9 промптов, а на задачах с кодом и математикой acceptance rate доходил до 87–89%, что давало 2.4–2.5x. Там же arkste завернул llama.cpp с MTP в Docker-образ (arkste/llama-swap-mtp:sm120) и показал похожие цифры на Q6_K_XL кванте: 111 tok/s с MTP против 53 без. Правда, у него квант тяжелее нашего, поэтому baseline ниже, зато MTP-слоям проще предсказывать.
А если смотреть шире, llama.cpp с MTP это ещё не потолок для RTX 5090. Есть vLLM с NVFP4 квантизацией, которая использует нативные FP4 тензорные ядра Blackwell. На Qwen3.5-27B люди получают ~5 300 tok/s на prefill и ~80 tok/s на decode при 200K контексте, а на MoE-версии через GPTQ-Int4 в vLLM 194–197 tok/s. Мы пока работаем в llama.cpp и GGUF-экосистеме, но тема vLLM + Blackwell-native кванты заслуживает отдельного исследования.
Сводная таблица
|
Модель |
Тип |
TG tok/s |
VRAM 32K |
Max ctx |
NIAH v3 |
|---|---|---|---|---|---|
|
Qwen3.6-35B-A3B Q4_K_M |
MoE |
274.8 |
21.8 ГБ |
256K |
82% |
|
Gemma 4 26B UD-Q4_K_XL |
MoE |
222.5 |
18.3 ГБ |
256K |
50% |
|
Mistral Small 3.1 Q4_K_M |
Dense |
101.5 |
19.3 ГБ |
64K |
54% |
|
Devstral Small 2 Q4_K_M |
Dense |
96.9 |
19.3 ГБ |
64K |
80% |
|
Qwen3.6-27B Q4_K_M |
Dense |
76.5 |
18.7 ГБ |
128K+ |
98% |
Выводы
Если по-честному, нет одной «лучшей» модели. Есть три сценария — и для каждого свой выбор.
Нужна максимальная скорость — Qwen3.6-35B-A3B. 275 tok/s, это ~4 слова в секунду для русского текста. Для чатбота, для API, для потокового вывода — хватает с запасом.
Нужен длинный контекст с надёжным качеством — Qwen3.6-27B. Да, 76 tok/s — это в 3.6 раза медленнее MoE-версии. Но 98% на NIAH до 128K — это уровень, которого ни одна другая модель в тесте не показала. Для RAG, для суммаризации документов, для code review длинных файлов — это правильный выбор.
Нужно что-то для кода — Devstral Small 2. 97 tok/s, файнтюн под инструкции, 84% на NIAH. Не рекорд ни по одному параметру, но крепкий середнячок без провалов.
Gemma 4 — красивая и быстрая, но с критическим ограничением: не использовать на контекстах больше 8K, если accuracy важна. На коротких задачах — прекрасна.
Сайт компании: https://gpugo.ru/
Наш телеграм-канал: https://t.me/GpuGo
ссылка на оригинал статьи https://habr.com/ru/articles/1056192/