Выбор агентской модели для кластеров из 2× DGX Spark (сентябрь 2026)

в 15:06, , рубрики: claude code, DGX Spark, gb10, NVFP4, prefix caching, vllm, локальные llm, спекулятивное декодирование, тензорный параллелизм

В сентябре 2026 года на Hugging Face есть 3 модели, которые хочется поставить на пару DGX Spark под Claude Code: DeepSeek‑V4.1-Flash на 552B, GLM-5.3-Flash на 320B и Qwen3.8-Flash‑Next на 125B. Первая лучше всех в бенчмарках, но не помещается в 243 ГиБ даже в 4 битах. Вторая занимает 198 ГБ и грузится 15 минут. Третья влезает в один спарк — если не считать 2 ГБ, которых ей не хватает. Ниже — почему на этом кластере выбор делает арифметика памяти, а не таблица бенчмарков, почему 6 миллиардов активных параметров не дают 90 ток/с, и почему для Claude Code решающим оказывается не tok/s, а один флаг vLLM, который в самом быстром конфиге выключен.

 3 модели, которые хочется поставить на пару DGX Spark под Claude Code: DeepSeek-V4.1-Flash на 552B, GLM-5.3-Flash на 320B и Qwen3.8-Flash-Next на 125B
3 модели, которые хочется поставить на пару DGX Spark под Claude Code: DeepSeek‑V4.1-Flash на 552B, GLM-5.3-Flash на 320B и Qwen3.8-Flash‑Next на 125B

Полтора месяца назад я развернул deepseek-ai/DeepSeek-V4-Flash-0731 тензорным параллелизмом на 2 узла. Замеренная скорость оказалась в районе 57 ток/с, и на какое‑то время это был лучший вариант из всех возможных. Потом за 3 недели вышли три новые модели, каждая из которых в таблицах выглядит лучше того, что у меня стоит, и вопрос «что ставить» встал заново. Метод с прошлого раза остался тот же: считать до скачивания, а не после.

Сначала — про сам стенд, потому что вся арифметика дальше отсчитывается от его чисел.

Стенд: два спарка с объединённой памятью

Внутри каждого спарка — суперчип NVIDIA GB10 Grace Blackwell: 20 ядер Arm v9.2-A (десять Cortex‑X925 плюс десять Cortex‑A725), блэкуэлловский GPU с compute capability 12.1 и теплопакет около 140 Вт.

Главное свойство этого железа — не терафлопсы, а объединённая память. 128 ГБ LPDDR5x-9400 на спарк — это одновременно системная память и видеопамять, отдельной VRAM нет вообще. Поэтому здесь не работает привычный конфиг вида «88 ГБ держим в видеопамяти, остальное выгружаем в хост»: выгружать некуда, это тот же самый пул, и такая «выгрузка» просто отнимает память у самой же модели. Пользователю из 128 ГБ достаётся 121,6 ГиБ, на пару — 243 ГиБ, и дальше в статье всё считается от этого числа.

Узлы соединены напрямую, без коммутатора: ConnectX-7, кабель QSFP56 из порта в порт. Мои замеры на этом соединении, снятые в июле: около 17 Гбит/с одним TCP‑потоком, около 107 Гбит/с 8 параллельными и около 19 ГБ/с на NCCL поверх RoCE, когда задействованы оба PCIe‑интерфейса карты: ConnectX-7 подключена к системе двумя отдельными интерфейсами PCIe Gen5 x4 и видна как два адаптера, а через один из них полоса упирается в 13,9 ГБ/с. Обычный гигабитный Ethernet между ними тоже есть — 943 Мбит/с по iperf3 — и нужен он только для управления. Веса больших моделей лежат на самих узлах.

Модель подключена к Claude Code через free‑claude‑code — шлюз, который принимает запросы в формате Anthropic API и переводит их в локальный vLLM. Claude Code обращается к шлюзу, и вместо всех моделей Claude — Opus, Sonnet, Haiku, Fable — подключена одна локальная.

Числа по текущему стеку, на которые я дальше опираюсь: веса DeepSeek-V4-Flash занимают 155 ГиБ и поделены поровну между двумя узлами, API‑сервер и планировщик vLLM работают на первом узле; модель даёт 57,54 ± 5,61 ток/с в один поток (медиана по прогонам — разброс между запусками на этом кластере около 20%, поэтому число и подаётся с сигмой, а не как точное), префилл 1600–2000 ток/с, KV‑пул около 699 тысяч токенов при окне 262 144 и холодную загрузку около 5 минут.

Калькулятор важнее бенчмарка

10 сентября вышла DeepSeek‑V4.1-Flash. По информации разработчика она обгоняет мой текущий стек по всем строкам, и первым рефлексом было качать. Вторым — открыть config.json.

У модели 552 миллиарда параметров в трансформере и ещё 196 миллиардов в Engram — таблице n‑грамм, которая читается на каждом токене. В 4 битах один только трансформер весит около 276 ГБ. У пары DGX Spark вместе 2 × 121,6 ГиБ = 243 ГиБ, и это без KV‑кэша. Модель не помещается ни в каком квантовании, при котором её ещё имеет смысл называть моделью: ей нужно 3 или 4 спарка, а у меня два (если у вас кластер из 4 спарков — такие конфигурации мне в сети попадались).

На этом месте обычно возникает мысль «а NVFP4?». Она мне тоже пришла, и она неверная: эксперты у DeepSeek изначально хранятся в MXFP4, 4 бита на вес. NVFP4 — это другая схема масштабирования при тех же 4 битах, а не уменьшение вдвое.

Итого лучшая модель месяца выбывает за 5 минут и без единого скачанного байта. Продолжаем с другими кандидатами.

Почему на двух Spark решает память, а не скорость соединения

Когда задействовано больше одного узла, то возникает опасение, что узким местом станет межузловое соединение, по которому на каждом токене идёт коллективная операция all‑reduce. Но если разобраться, то при тензорном параллелизме MoE‑модели на каждом токене через соединение ходит вектор скрытого состояния, это единицы мегабайт, а интерфейс пропускает 18–19 ГБ/с. Соединение нагружено на доли процента.

По факту все упирается в память.

Во‑первых, объём. Тензорный параллелизм — это способ запустить одну модель на нескольких GPU, при котором каждая матрица весов режется на части, и каждый узел хранит и считает только свою часть; результаты частичных вычислений затем объединяются между узлами той самой операцией all‑reduce. Поэтому всё, что в весах, должно поместиться в 243 ГиБ, и делится оно пополам между узлами. Для 198 ГБ (≈184 ГиБ) GLM это 92 ГиБ весов на узел из 121,6 доступных. При gpu-memory-utilization 0.85 под KV‑кэш и активации остаётся порядка 11 ГиБ на узел — вот почему в конфиге размер KV‑кэша зафиксирован флагом --kv-cache-memory 6 GiB, а не оставлен автоматическому выбору.

Во‑вторых, пропускная способность памяти. Токен при декоде — это чтение всех активных весов из памяти. У GB10 паспортная полоса 273 ГБ/с (цифра вендора, я её не мерил). У GLM активных 18B, в 4 битах это около 9 ГБ на токен; поделено между двумя узлами — 4,5 ГБ на каждом. Делим: потолок около 60 ток/с в один поток без спекуляции. Это грубая оценка, но именно она, а не бенчмарки, говорит, что быстрее 60 ток/с на этой модели не будет, и любые «100 ток/с» из чьих‑то карточек надо читать как результат спекулятивного декодирования, а не самой модели.

Той же арифметикой Qwen3.8-Flash‑Next с 6B активных параметров должна давать скорость в 3 раза выше. Однако, это не так не, и об этом вторая половина статьи.

GLM-5.3-Flash, 198 ГБ и 15 минут загрузки

GLM-5.3-Flash вышла 26 августа: 320B параметров, 18B активных, MIT, поддержка изображений, миллион контекста нативно. У z.ai есть таблица, где она в Claude Code показывает 29,0 на Code Bench против 29,5 у Opus 4.8. Цифра из блога разработчика, но одна деталь в ней важнее самой цифры: бенчмарк запускали внутри Claude Code 2.1.207, то есть именно в том сценарии, ради которого мне нужен кластер.

На HF под неё есть две NVFP4-версии, и первая же ловушка — выбрать не ту. ModelOpt‑версия от NVIDIA портит токены вызова инструментов: вместо аргумента приходит повреждённая строка, и Claude Code молча теряет tool_call (vLLM #54150). Рабочая версия — RedHatAI/GLM-5.3-Flash-NVFP4 в формате compressed‑tensors W4A4, 10 шардов по 20 ГБ плюс 7,6 ГБ MTP‑головы, итого около 198 ГБ.

Конфиг на пару DGX Spark у tonyd2wild собран целиком: свой образ vLLM под sm121, черновая модель DFlash2 на 2,3 ГБ для спекулятивного декодирования с k = 7, патч индексатора разреженного внимания, который на SM121 иначе завершается ошибкой в top‑k, --block-size 2304, KV‑кэш в fp8, --enforce-eager. По его README в один поток на задачах с кодом — 46,9 ток/с, при 5 параллельных запросах — 56 в сумме, KV‑пул 581–678 тысяч токенов, холодная загрузка около 15 минут. Против моего измеренного потолка в 60 это 78% — со спекуляцией, что правдоподобно.

Пара важных строчек из README:

  1. Swap должен быть включён, со swappiness=0, иначе загрузка 198 ГБ через оперативную память не выдерживает пикового потребления. У меня swap выключен на обоих узлах, и это не случайность. С выключенным swap попытка выйти за 128 ГБ сразу кончается явной ошибкой CUDA OOM. С включённым — машина уходит в подкачку на часы: формально она жива, но работать не может.

  2. Перед стартом — echo 3 > drop_caches, иначе page cache от предыдущей модели занимает память, которая нужна загрузчику. Ритуал, который выглядит как суеверие, пока не увидишь OOM на 190-м гигабайте.

Qwen3.8-Flash‑Next, 133 ГБ и спарк, в который он влезает не целиком

Qwen3.8-Flash‑Next — превью четвёртого поколения Qwen: 125B параметров, 6B активных, плюс 51B в таблице n‑грамм PLE и 4B в MTP‑голове; 262K контекста нативно, миллион через YaRN, поддержка изображений. Квантованная версия nvidia/Qwen3.8-Flash-Next-NVFP4 весит около 133 ГБ, и в карточке NVIDIA написано, что по качеству NVFP4 здесь неотличим от FP8.

Первое, что бросается в глаза: 133 ГБ — это почти ровно один спарк. Почти: 121,6 ГиБ — это 130,5 ГБ, и модели не хватает 2,5 ГБ. Конфиг TP1 на одной Spark всё равно существует — за счёт того, что таблица PLE подгружается по частям и не хранится в памяти целиком, — и даёт 43,9 ток/с против 53,7 на двух. Это единственный из трёх кандидатов, который в принципе может работать на одном узле: без межузлового соединения, без двухузлового запуска, без all‑reduce на каждом токене. Оба спарка у меня всё равно уйдут под модель, так что ставить я буду TP2 — но само наличие односерверного варианта уже интересно.

Второе — цифры TP2. Тот же автор на двух спарках получает 53,7 ток/с медианой в один поток, 97,9 в сумме на 6 потоках, и KV‑пул 1,97 миллиона токенов. Последнее число — в 3 раза больше, чем у GLM, и это прямое следствие 6B активных параметров: сама модель лёгкая, память достаётся кэшу.

Третье — строчка в конфиге, которая для агентного сценария важнее всех чисел выше: --no-enable-prefix-caching. Prefix caching у Qwen3.8-Flash‑Next в vLLM выключен принудительно, потому что с ним модель отдаёт неверные ответы (vLLM #54173).

6 миллиардов активных параметров не дают 90 ток/с

Вернёмся к оценке потолка скорости через пропускную способность памяти — той, что дала около 60 ток/с для GLM. У GLM 18B активных параметров, у Qwen — 6B. Если потолок GLM — около 60 ток/с, то у Qwen он должен быть около 180. Конфиг даёт 53,7. Это 30% от потолка против 78% у GLM, и разница слишком велика, чтобы списать её на разброс.

Основные причины:

  • Таблица PLE. 51 миллиард параметров, которые не считаются «активными», но читаются на каждом токене. Сколько именно байт — зависит от n‑граммы и от того, как выполняется gather; в README про это ничего нет.

  • Накладные расходы на запуск CUDA‑ядер. При 6B активных параметров сами матричные вычисления настолько коротки, что доля запуска ядер, all‑reduce и планировщика перестаёт быть пренебрежимо малой. В конфиге tonyd2wild для Qwen видно, что автор боролся именно с этим: захват CUDA‑графов, который убирает стоимость запуска ядер, включён только для декода, а спекулятивное декодирование через MTP‑голову настроено так, чтобы за один проход модели предсказывать 3 токена вместо 1 — то есть платить накладные расходы 1 раз на 3 токена.

Выбор агентской модели для кластеров из 2× DGX Spark (сентябрь 2026) - 2

Практический вывод: «активные параметры» — плохой предиктор скорости, когда их становится меньше 10 миллиардов. Между 18B и 6B активных параметров разницы в скорости почти нет: 47 против 54 ток/с. Разница есть в другом — в размере KV‑пула и в том, что одна из двух моделей помещается в один спарк.

Где расчёт расходится с замером — и почему я публикую его как есть

Оценка потолка через полосу памяти — это модель с двумя допущениями:

  • 273 ГБ/с — паспортная цифра, а реальная полоса под vLLM ниже, и насколько — я не мерил.

  • Я считаю, что за токен читаются только активные веса; на деле читаются ещё KV‑кэш, у GLM — индексатор разреженного внимания, у Qwen — PLE.

Обе поправки тянут потолок вниз, так что 78% для GLM — это, скорее всего, ближе к 90% от реального потолка, а 30% для Qwen — к 40%.

Я оставляю расчёт в таком виде, потому что он сделал свою работу: отсёк DeepSeek‑V4.1 и объяснил, почему у двух моделей с трёхкратной разницей в активных параметрах одинаковая скорость. Дотягивать его до «измерения» я не буду — измерение будет в следующем посте, когда одна из двух моделей будет запущена на этой паре.

Сводная таблица того, что известно на сегодня. Курсивом — мои, обычным — чужие числа.

DeepSeek‑V4-Flash (текущая)

GLM-5.3-Flash NVFP4

Qwen3.8-Flash‑Next NVFP4

Параметров / активных

284B / 13B

320B / 18B

125B (+51B PLE) / 6B

Веса на диске

155 ГиБ

≈198 ГБ

≈133 ГБ

Помещается

два спарка

два спарка

два или один

Single‑stream, ток/с

57,5 ± 5,6

46,9 (со спекуляцией)

53,7 (TP2), 43,9 (TP1)

KV‑пул, токенов

≈699K при 262K

581–678K

≈1,97 M

Prefix caching

включён

включён

выключен (#54173)

Загрузка

~5 мин

≈15 мин

в README не указано

Ловушки

—

swap включён, drop_caches, не ModelOpt

PLE, YaRN только в text_config

Следствие: для Claude Code выбор делает не tok/s, а prefix cache

Claude Code — это не чат. Каждый запрос агента отправляет на сервер один и тот же системный промпт с описанием ~150 инструментов, всю историю диалога и в конце — новую реплику. Для сервера это означает, что 95% промпта совпадают с предыдущим запросом, и весь смысл prefix caching в том, чтобы не считать их заново.

У меня есть свои числа на этот счёт, снятые в августе с логов шлюза на текущем стеке. Запросы, у которых в prefix cache попадало больше 80% промпта, получали первый токен за 4,3 с. Запросы с попаданием ниже 20% при том же размере промпта ждали 73,2 с. Разница в 17 раз при одинаковой модели, одном железе и одинаковой длине — и она целиком объясняется тем, считался ли префикс заново.

Теперь приложите к этому --no-enable-prefix-caching в конфиге Qwen. Модель при 1600–2000 ток/с префилла (моя цифра для DeepSeek; у Qwen с 6B активных параметров префилл должен быть быстрее, но порядок тот же) на каждом ходу агента с контекстом в 100 тысяч токенов будет считать эти 100 тысяч заново. Это минута ожидания перед каждой репликой, и никакие 53,7 ток/с декода её не компенсируют: агент генерирует ~200 токенов на ход, а читает — 100 тысяч.

Поэтому порядок кандидатов у меня получился таким, каким он не получился бы по таблице бенчмарков: первым идёт GLM-5.3-Flash, потому что он ничем не отличается от текущего стека по способу работы и уже сравнивался с Opus внутри Claude Code. Qwen3.8-Flash‑Next — вторым, и у него один входной билет: если prefix caching у него включается без искажения ответов, он выигрывает по пулу в 3 раза и освобождает второй узел. Если нет — он остаётся моделью для чата, а не для агента, какой бы быстрой ни была.

Выводы

  1. Первый фильтр для модели на двух DGX Spark — не бенчмарк, а сумма весов против 243 ГиБ. Модель, которая не проходит этот фильтр, не нужно даже читать: DeepSeek‑V4.1-Flash на 552B отсекается за 5 минут.

  2. NVFP4 не уменьшает модель, у которой эксперты уже в MXFP4. Если в карточке исходника написано «FP4», четырёхбитная производная будет того же размера.

  3. Потолок декода считается из полосы памяти и активных параметров, и его стоит посчитать до чтения чужих тысяч tok/s: для 18B активных параметров на GB10 это около 60 в один поток, всё сверху — спекулятивное декодирование.

  4. Ниже 10B активных параметров их число перестаёт предсказывать скорость: 6B у Qwen и 18B у GLM дают 54 и 47 ток/с. Ищите, что ещё читается на токене — PLE, индексаторы, KV.

  5. Для агентного сценария смотрите не на tok/s, а на prefix caching: на моём шлюзе разница между попаданием и промахом — 4,3 против 73,2 с до первого токена. Конфиг, в котором кэш префикса выключен, для Claude Code не подходит, какой бы быстрой ни была модель.

  6. Конфиг, который требует включить swap, меняет политику памяти всей машины, а не одну строчку в конфиге. У меня он выключен ради честного OOM вместо тихой подкачки, и включать его — решение, которое принимается до установки, а не после первого зависания на 190-м гигабайте.

  7. Прежде чем выбирать модель для сервиса, проверьте, что сервис включён.


Источники: RedHatAI/GLM-5.3-Flash‑NVFP4, nvidia/Qwen3.8-Flash‑Next‑NVFP4, конфиги tonyd2wild для GLM-5.3-Flash на двух Spark и Qwen3.8-Flash‑Next, vLLM issues #54150 и #54173, блог z.ai о GLM-5.3-Flash.

Автор: nikkoris

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js