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

Qwen 3.8 27B на RTX 3090: 21 день автономной разработки CUDA-движка

Локальный агент на Qwen 3.8 27B (Q4, KV-кэш Q8, контекст 200k) за 21 день написал CUDA-инференс-движок на одной RTX 3090: рабочие кернелы, ~250 tps prefill прот

Коротко

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

  1. 01

    Что получилось: итоги 21-дневного прогона

  2. 02

    Конфигурация: Qwen 3.8 27B в Q4, KV-кэш Q8 и 200k контекста на RTX 3090

  3. 03

    Как был устроен агентный цикл и правила, которые его удерживали

  4. 04

    Конфликт за одну GPU: vLLM против тестируемого движка

Что получилось: итоги 21-дневного прогона

Локальный агентный цикл на одной RTX 3090 с моделью Qwen 3.8 27B отработал около 21 дня и довёл задачу «написать CUDA-инференс-движок под архитектуру собственной видеокарты» до рабочих кернелов и бенчмарков. Человек за весь прогон отправил примерно 12 сообщений, остальное время цикл шёл сам.

Итог без прикрас: рабочий код и замеры есть, победы над llama.cpp нет. По prefill агент упёрся примерно в 250 токенов в секунду, тогда как llama.cpp на той же карте выдаёт около 700 токенов в секунду. Это примерно половина от готового решения, и именно здесь виден потолок эксперимента.

Главный вывод автора: квантованная 27B на потребительской видеокарте способна неделями удерживать инженерную цель, оставляя после себя рабочий код, бенчмарки и заметки. Автор отчёта не пишет на CUDA, то есть кернелы появились не благодаря его квалификации в этой области. Полный отчёт опубликован в r/LocalLLaMA.

Стек прогона: Qwen 3.8 27B в квантовании Q4, KV-кэш Q8, контекст 200k, deepseek harness. Автор выложил дамп протокола и правил (~15 ГБ) и бэкенд HyperQwen.

Конфигурация: Qwen 3.8 27B в Q4, KV-кэш Q8 и 200k контекста на RTX 3090

24 ГБ памяти RTX 3090 задают рамки, и набор параметров в этом прогоне выстроен вокруг одного ограничения: длинная история работы агента должна помещаться в видеопамять вместе с весами модели.

Q4 на весах сокращает объём, который занимает сама модель. KV-кэш в Q8 держит историю attention в 8-битном формате вместо FP16, что примерно вдвое уменьшает расход памяти на кэш. Контекст 200k нужен не для красоты: пока история влезает целиком, цикл работает без потери деталей, а компакция требуется только тогда, когда окно действительно переполняется.

Точных замеров потребления VRAM в опубликованном отчёте нет, поэтому подбирать параметры придётся под свой сетап. Общая логика простая: чем длиннее контекст, тем меньше остаётся на батч, на сам движок и на параллельные процессы.

Поведение Qwen 3.8 27B на другом железе и в другом бэкенде разобрано отдельно: RTX 3090 против MacBook M5 Pro, где та же модель дала около 20 токенов в секунду на Mac и порядка 100 токенов в секунду на Linux с vLLM.

Как был устроен агентный цикл и правила, которые его удерживали

Прогон держал не размер модели, а written rulebook. В правилах прописали роли, передачи между ними, условия для пинга автора, прямой запрет копировать llama.cpp и запрет объявлять задачу невыполнимой в одиночку. Последний пункт закрывает частый сценарий провала автономного цикла: агент упирается в сложность и объявляет её непреодолимой.

Автор отдельно отмечает: остановки агента были в основном связаны с протоколом, а не с тем, что модель ушла от задачи. Харнесс один раз жёстко упал, и автор перезапустил его вручную.

Роли, передачи и пинг автора: как выглядел протокол

  • Роли с разделением зон ответственности, чтобы один процесс не отвечал за всё сразу.
  • Передачи (handoff) как обязательный шаг: результат фиксируется и передаётся дальше, а не остаётся в контексте одного субагента.
  • Условия для пинга автора: агент не дёргает человека по любому поводу, но обязан позвать в описанных случаях.
  • Запрет копировать llama.cpp: решение не должно сводиться к переписыванию готового движка.
  • Запрет объявлять задачу невыполнимой в одиночку: перед таким выводом нужна эскалация.
  • Фиксированный скрипт передачи с записью STATE, о котором ниже.

Правила в текстовом виде работают как артефакт, который агент перечитывает после каждой компакции. Без этого после сжатия контекста из памяти выпадает сама договорённость о том, как вести работу. Дамп протокола и правил (~15 ГБ) автор выложил публично.

Как выстраивать последовательную оркестрацию с супервизором и субагентом, чтобы не убивать KV-кэш, разобрано в отдельном материале: один агент за раз на слабом GPU.

Конфликт за одну GPU: vLLM против тестируемого движка

Одна RTX 3090 обслуживала сразу две стороны: vLLM хостил агентов, а тестируемый CUDA-движок требовал видеопамять под бенчмарки. Оба претендуют на всю карту. Убить vLLM неправильным способом - все агенты разом умолкают. Оставить vLLM работать во время замера - OOM.

Инцидент показателен: один субагент счёл фиксированное окно необязательным, убивал vLLM вне разрешённого времени, уронил оркестратор и повторил это ещё раз. Харнесс тоже один раз жёстко упал.

Фиксированный скрипт передачи: как не уронить оркестратор

Протокол требует проводить передачу GPU строго по шагам:

  1. Остановить vLLM.
  2. Провести бенчмарк тестируемого движка.
  3. Запустить vLLM обратно.
  4. Опрашивать health до восстановления сервиса.
  5. Записать STATE.

Сбой возникает не из-за сложности шагов, а из-за их нарушения по таймингу. Лечится блокировками и уточнением протокола: трогать vllm.sh разрешено только определённой роли. Так борьба за одну видеокарту превращается из гонки процессов в очередь.

Накладные расходы: 180 субагентов, 230M токенов и 699 компакций

За прогон накопилась статистика, которая показывает реальную цену автономности:

  • 180 субагентов.
  • около 230M токенов вход плюс выход.
  • примерно 1.7B токенов чтения кэша (cache-read).
  • 699 компакций, которые суммарно заняли около 83 часов.

83 часа внутри компакций, это примерно 17% календарного времени. Почти каждый шестой день прогона уходил на сжатие истории, а не на написание кода. Типичная компакция занимает около 7 минут на промпте размером более 160k токенов.

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

Результаты бенчмарков: ~250 tps prefill против ~700 tps у llama.cpp

Сравнение однозначное. llama.cpp на той же RTX 3090 даёт около 700 токенов в секунду на prefill, агент дошёл примерно до 250. Речь именно о prefill, то есть обработке входного промпта, а не о генерации ответа.

Хронология показательна: около дня 6 у агента уже было несколько рабочих кернелов, а prefill всё равно стоял на уровне ~250 tps. Позже наблюдался тот же паттерн. Прогресс в объёме кода не превратился в прогресс по ключевой метрике.

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

Чем prefill отличается от decode и как честно сравнивать движки на одной карте, разобрано в материале про Qwen 3.8 27B на RTX 5090 и nInfer.

Что выложил автор: HyperQwen и дамп протокола на 15 ГБ

Для самостоятельного изучения доступны два артефакта:

  • дамп протокола и правил объёмом около 15 ГБ, то есть рабочая история цикла вместе с текстом правил;
  • бэкенд HyperQwen, репозиторий syv-ai/HyperQwen. В отчёте u/iamMess упомянут как автор работы над этим бэкендом.

Дамп полезен тем, кто хочет увидеть протокол в действии, а не в пересказе: по нему видно, как формулировались передачи, как выглядели пинги автора и как цикл восстанавливался после сбоев. Содержимое дампа, кроме протокола и правил, автор в отчёте не расписывает, поэтому рассчитывать на готовую инструкцию внутри не стоит.

Кому подходит такой сетап и какие у него ограничения

Ограничения стоит назвать прямо:

  • одна GPU делится между агентами и тестируемым движком, без жёсткого протокола передачи это гарантированные падения и OOM;
  • prefill отстаёт от llama.cpp примерно вдвое;
  • компакции съедают около 17% календарного времени;
  • харнесс может упасть, и перезапуск остаётся за человеком;
  • финальный результат уступает готовому движку по ключевой метрике.

Кому это подходит: тем, у кого есть инженерная задача на недели и одна потребительская видеокарта, при готовности мириться с накладными расходами и следить за протоколом. Порог входа ниже, чем кажется: автор не пишет на CUDA, а участие человека свелось к ~12 сообщениям за 21 день.

Кому не подходит: тем, кому нужен продакшн-инференс. Там выигрывает llama.cpp, и это подтверждается замерами на той же карте. Автономный цикл даёт артефакты и рабочий код, но не заменяет зрелый движок под нагрузкой.

Логика переносится и на другие конфигурации: похожий сценарий с длинным контекстом на одной машине разобран в кейсе про Qwen3.8-Flash-Next на NVIDIA DGX Spark. Критичные факторы одинаковые: помещается ли история в память, есть ли фиксированные правила и кто отвечает за передачу ресурса.

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