Перейти к содержимому
Экосистема AI Vibe

Разборы

Три деплоя Gemma 4 на одном T4G за $3: что меняет runtime, а что нет

Редакция 3 сентября 2026 г.

Три деплоя Gemma 4 на одном T4G за $3: что меняет runtime, а что нет

Соло-разработчик, который поднимает локальный вывод модели рядом с IDE, а не только в управляемом API, обычно сравнивает vLLM, JAX и PyTorch по tok/s из чужих таблиц. В бенчмарке на одном чекпоинте google/gemma-4-E2B-it, одном GPU AWS G5g и едином контуре тестов автор показал обратное: лидер по decode и лидер по cold boot — разные стеки, а весь эксперимент уложился в меньше $3.

Почему один контур тестов важнее трёх красивых цифр

Типичная ловушка при выборе LLM runtime — три разных скрипта, три разных метрики, три разных вывода. Автор изначально гонял vLLM, JAX и PyTorch отдельно и получил несопоставимые числа: у vLLM не было поля usage.decode_tokens_per_second, sweep не мог смотреть на vLLM-rig, а prefix cache с hit rate 94,7% дал невозможный «30×» по TTFT, потому что warmup и repeats переиспользовали один prompt.

Решение — общий клиент sweep.py с флагом --decode-source {auto,usage,stream,both} и портативным decode через разрыв между токенами на wire у OpenAI-compatible серверов. Режим stream считает TPOT так же, как vllm bench serve: (latency - ttft) / (output_len - 1). Калибровка stream/gauge не переносится между rig: JAX 0,9799, PyTorch 0,9543 — cross-rig таблица decode строится только из stream.

Ошибки ловятся измерением на одной статистике, а не рассуждением в трёх разных контурах.

Decode-рейтинг и lifecycle-рейтинг расходятся

На concurrency 1 (stream, 12/12 или 10/12 ячеек) decode tok/s выглядит так:

Место Runtime decode tok/s % от ceiling 61,4
1 vLLM 32,53 53,0%
2 JAX 12,69 20,7%
3 PyTorch 10,24 16,7%

vLLM в 3,18× быстрее PyTorch по decode. Ни один runtime не упирается в bandwidth ceiling 61,4 tok/s при batch 1.

Cold boot — другая картина (9 cold + 9 warm; старт с момента возврата id из run_instances):

Место Runtime cold boot warm reload
1 PyTorch 195,2 s 24,5 s
2 JAX 242,2 s 74,1 s
3 vLLM 1417,8 s (23m 38s) 264,3 s

PyTorch до serving в 7,3× быстрее vLLM по lifecycle. Смена serving-кода: PyTorch ~25 s против ~67 min rebuild from source у vLLM. Health ≠ ready: JAX отдаёт health 200, но first completion cold — 22,9 s (XLA compile per shape); vLLM — slowest boot, fastest first token (0,5 s cold).

Для агента рядом с IDE это практический выбор: нужен быстрый decode на длинных ответах — vLLM; нужен короткий цикл «поднял — проверил — переключил стек» — PyTorch выигрывает по boot.

Пять гипотез, которые измерение сняло с повестки

Эксперимент «поймал пять неверных утверждений» — не метафора. Ядро — блок про доминирование загрузки весов в cold boot vLLM (468–561 s): четыре гипотезы опровергнуты, пятая оставлена непроверенной.

  1. g5g.2xlarge не нужен swapfile — ускорит boot. Опровергнута трёхкратной кампанией cold boot (23m 38s).
  2. Больший хост «точно» исправит boot. Снята в тот же день — большой хост не измеряли.
  3. Больший хост «очень правдоподобно» исправит boot. Опровергнута одним boot на g5g.4xlarge: RAM 11,19→26,49 GiB, загрузка весов 546→468 s, total boot −4,7% (внутри шума).
  4. Виноват loader; auto-prefetch disabled на EXT4. Опровергнута A/B: 76,13 s vs 75,12 s с --safetensors-load-strategy=prefetch (−1,3%).
  5. EBS лениво гидратирует том из AMI snapshot. Непроверена — автор не повышает до факта без измерения.

Дополнительно: gauge JAX с одним знаком после запятой давал byte-identical 12,8, 12,8, 12,8; после фикса — 12,962 tok/s. Poll health каждые 5 s квантовал два boot в одинаковые 214,4 s и 125,1 s — кампания перезапущена с poll 0,5 s.

MCP-оркестрация деплоя вместо ручного SSH

Пост не ограничивается бенчмарком: набор Python-инструментов MCP упрощает управление каждым деплоем. Named tools в тексте — check_g5g_quotas, get_install_progress, verify_gpu_arch, deploy_torch_server, verify_model_health, terminate_g5g_instance. Remote ops идут через AWS Systems Manager без inbound SSH и private key.

Для соло-workflow с агентами это прямой сигнал: сравнение трёх LLM runtime на облачном GPU можно автоматизировать инструментами MCP, а не ручным циклом «зашёл на инстанс — поставил wheel — забыл убить». Стратегия MCP для сравнения нескольких runtime подтверждена пошаговым подходом, без ручного SSH.

Код контура тестов и sweep — в монорепо gemma4-dev.

Сколько стоит такой эксперимент и где границы вывода

19 инстансов, 4,06 h g5g.2xlarge + 0,38 h g5g.4xlarge — суммарно меньше $3. Верхние границы в cost_derivation.md репозитория: $1,84 all-spot, $2,68 all-on-demand. Spot premium 26–46% на этом железе.

Железо: 1× NVIDIA T4G, SM 7.5, 15 360 MiB; инстанс g5g.2xlarge (8 vCPU Graviton2 aarch64, 16 GiB host RAM). Веса dense — 9,5 GiB float16; чекпоинт ~2B effective из ~5B total. Все три runtime — float16 (Turing без bfloat16/fp8).

Оговорки scope, которые нельзя размывать:

  • Только concurrency 1 — latency, не serving throughput; continuous batching vLLM не тестировался.
  • PyTorch/JAX в этой setup не умеют concurrent serve.
  • max_model_len: vLLM 16384, JAX/PyTorch 4096; JAX leg — quantised shipped config против двух dense runtime.
  • Пост ограничен AWS G5g в us-east-1; перенос на домашний GPU автор не заявляет.

Если выбираете стек для собственного вывода модели под агента — смотрите не только decode tok/s, но и cold boot, warm reload и стоимость итерации. Три runtime на одном T4G за копейки — дешёвый способ не повторить чужие «five wrong claims».

Источники