Загрузка...

Qwen3.6 UD-Q4_K_XL на RTX 3060 12 ГБ: как я запускаю её через llama.cpp-moe с окном 128K

Qwen3.6 UD-Q4_K_XL на RTX 3060 12 ГБ: как я запускаю её через llama.cpp-moe с окном 128K

У меня дома обычный ПК: Ryzen 5 5600, RTX 3060 на 12 ГБ и 32 ГБ DDR4. На нём я гоняю локальную модель для помощи с кодом, и после серии замеров (как сравнивал модели, рассказал в отдельной заметке) остановился на Qwen3.6-35B-A3B в кванте UD-Q4_K_XL. Здесь я показываю команду, с которой она у меня работает, объясняю, зачем в ней каждый флаг, и сколько она реально выдаёт по памяти и скорости. Цифры актуальны на 9 ноября 2026 года.

Сразу оговорюсь, чего здесь нет. Сборку движка с нуля я не расписываю. И ещё: в команде есть файл профиля экспертов (о нём ниже), который у меня свой, локальный. Без него та же строка на другой машине может вести себя иначе.

Что за модель и чем запускаю

Модель беру из репозитория unsloth/Qwen3.6-35B-A3B-MTP-GGUF, файл Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf, он весит 22,85 ГБ (21,28 ГиБ). Квант — это степень сжатия весов. Кванты unsloth с приставкой UD смешанные: разные части модели сжаты по-разному, и у этого файла в среднем выходит около 5,2 бита на вес вместо исходных 16. Модель становится в разы меньше и чуть теряет в точности.

Qwen3.6-35B-A3B устроена как MoE (Mixture of Experts, «смесь экспертов»). Это видно и по названию: 35B — всего около 35 млрд параметров, A3B — на каждый токен работает лишь около 3 млрд. В слое у неё 256 «экспертов», и для каждого токена модель выбирает 8 из них. Поэтому 35B-модель вообще можно запустить на 12-гиговой карте с приличной скоростью: всех экспертов держать в видеопамяти не нужно.

Запускаю не обычным llama.cpp, а форком llama.cpp-moe (thecodacus/llama.cpp, ветка perf, коммит 906247a58f0d28cd8537999f1feceb441029392d). Главное в нём — кэш экспертов: самые востребованные эксперты лежат в видеопамяти, а остальные считаются на процессоре.

Команда

Ниже команда, на которой я снимал все замеры из этой заметки. Пути указаны относительно корня моего проекта:

llama-server --host 127.0.0.1 --port 8081 --parallel 1 -fa on --jinja --mmap \
  -m models/Qwen3.6-35B-A3B-MTP/Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf \
  -ngl 99 --n-cpu-moe 99 -ctk q8_0 -ctv q8_0 -t 6 -tb 6 -b 2048 -ub 1024 \
  --moe-cache-profile runtime/llamacpp-moe/profiles/qwen35b-merged.csv \
  --sched-async-cpu -c 131072 --moe-cache-slots 48 \
  --spec-type draft-mtp --spec-draft-n-max 2

Проверить, что сервер поднялся, можно так:

curl -sf http://127.0.0.1:8081/health

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

llama-server -m models/Qwen3.6-35B-A3B-MTP/Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf -ngl 99 --n-cpu-moe 99 -fa on \
  -ctk q8_0 -ctv q8_0 -c 131072 --parallel 1 -t 6 -tb 6 -b 2048 -ub 512 --cache-reuse 256 \
  --host 127.0.0.1 --port 8080 --jinja --no-mmap --context-shift \
  --spec-type draft-mtp --spec-draft-n-max 2 \
  --moe-cache-profile runtime/llamacpp-moe/profiles/qwen35b-merged.csv --moe-cache-slots 48 --sched-async-cpu

Разница в том, что лаунчер работает на порту 8080, берёт -ub 512 вместо 1024, загружает веса целиком в память (--no-mmap) и включает --cache-reuse 256 и --context-shift. Слоты, KV-кэш и MTP те же. Но цифры скорости ниже сняты на тестовой команде, на лаунчере я их отдельно не мерил.

Что делает каждый флаг

Флаг Зачем он
--host 127.0.0.1 --port 8081 Сервер слушает только локально, наружу не торчит.
--parallel 1 Один запрос за раз. Для одного человека больше и не надо, а память расходуется предсказуемо.
-fa on --jinja --mmap Flash attention, шаблон чата модели (Jinja) и чтение весов с диска через mmap.
-ngl 99 --n-cpu-moe 99 Все слои идут на видеокарту, а веса экспертов остаются в оперативке. Какие эксперты всё же попадут в видеопамять, решает кэш ниже.
-ctk q8_0 -ctv q8_0 KV-кэш в 8 битах, чтобы длинный контекст влез в 12 ГБ.
-t 6 -tb 6 -b 2048 -ub 1024 Шесть потоков под шесть ядер Ryzen 5 5600 и размеры пакетов при чтении запроса.
--moe-cache-profile …csv Профиль: какие эксперты чаще нужны и поэтому стоят первыми в очереди в видеопамять.
--moe-cache-slots 48 Сколько экспертов на слой держать в видеопамяти.
--sched-async-cpu Пока видеокарта считает «горячих» экспертов, процессор параллельно досчитывает остальных.
-c 131072 Окно контекста в 131072 токена, те самые «128K».
--spec-type draft-mtp --spec-draft-n-max 2 MTP: модель угадывает до двух токенов вперёд.

Пара терминов, которые встречаются дальше. Контекст — это сколько текста модель держит в голове за один запрос: ваш вопрос, приложенный код и её собственный ответ. KV-кэш — память, где хранится уже прочитанная часть контекста, чтобы не пересчитывать её на каждом токене. Чем длиннее окно, тем больше этот кэш, поэтому я храню его в 8 битах (q8_0), а не в 16.

MTP (Multi-Token Prediction) — встроенный в Qwen3.6 механизм «черновика». Модель быстро предлагает до двух следующих токенов, а потом одним проходом проверяет, правильно ли угадала. Если угадала, за шаг получается больше одного токена, и генерация ускоряется.

Откуда взялись 48 слотов и CSV-профиль

Профиль qwen35b-merged.csv — это файл маршрутизации: в нём записано, к каким экспертам модель обращается чаще всего. Он лежит только у меня, поэтому тот, кто повторит команду без него, должен понимать, что получит другую картину.

Число слотов я подбирал под бюджет: видеопамяти вместе с рабочим столом должно уходить не больше 11 ГБ. С 56 слотами на 64K контекста пик дошёл до 11,6 ГБ, это уже перебор. С 48 слотами пик на калибровке был 10403 МиБ, и это с рабочим столом. Оперативки при этом оставалось свободно не меньше 22,7 ГБ, своп стоял на месте, около 4,2 ГБ, без постоянной подкачки. Больше 56 слотов на Q4 я не пробовал.

Сколько это даёт по скорости

Тут важно различать две скорости. Prefill — это как быстро модель читает ваш запрос. Decode — как быстро она пишет ответ. Когда я пишу «ток/с» без уточнения, речь о генерации ответа.

Что мерил Результат Пояснение
Пик видеопамяти (48 слотов) 10403 МиБ Вместе с рабочим столом, цель была не больше 11 ГБ
Генерация на запросе ~8K 44,5–48 ток/с 44,5 с холодного старта, 48 на повторном запросе
Генерация при ~100K заполненного контекста 35,6–36,6 ток/с Окно уже почти забито
Чтение запроса (prefill) на 8K 374–456 ток/с 374 с холодного старта, 456 на повторном запросе
Чтение запроса (prefill) на ~100K ~399 ток/с С холодного старта

Когда я говорю «около 36 токенов в секунду на 128K», имею в виду генерацию, когда в контексте уже лежит около 100 тысяч токенов. Это не замер с пустого старта, и ровно на 131072 токенах я такую скорость отдельно не проверял. На коротких запросах модель заметно быстрее, так что «128K работает как 8K» обещать не буду.

128K на деле: что реально проверено

-c 131072 — это размер окна, а не гарантия, что всё до последнего токена работает одинаково хорошо. Самый длинный вход, который я реально прогнал, — 102831 токен: в этой задаче модель читает большой PHP-код и отвечает строгим JSON. Она прошла все три повтора, модель читала вход со скоростью 398–420 ток/с и отвечала со скоростью 36,0–39,8 ток/с. Это мой максимум проверенного, а не обещание, что любой сценарий на полных 128K будет таким же быстрым и стабильным.

Если сравниваете эту модель с той, у которой окно меньше 102831 токена, эту задачу придётся выкинуть. Тогда в зачёте остаётся 39 попыток вместо 42.

Насколько хорошо она пишет код

Качество я проверял не агентом с инструментами, а проще: модель получает фиксированный запрос, даёт один ответ, и его автоматически проверяют.

Первый набор — 15 задач на PHP из HumanEval-PHP, по три попытки на каждую (сиды 42, 43, 44), температура 0,2, лимит 8192 токена вместе с рассуждениями. Решения проверяются скрытыми тестами в Docker. Итог — 44 из 45. Единственная ошибка была в задаче modp на сиде 42.

Второй набор — мои «жизненные» задачи (Realworld): 14 штук по три повтора. Там нужно написать PHP-функцию, поправить сразу несколько файлов, прочитать большой PHP-код и ответить строгим JSON (на 38 386 и 102 831 токен), вытащить JSON из текста и вызвать инструменты. Температура 0, на рассуждения отведено 6144 токена, общий лимит 8192. Итог — 36 из 42, ни один ответ не оборвался по лимиту. Шесть ошибок пришлись на две задачи, каждая провалилась во всех трёх повторах: m2 (правка роутера, ответ «Not Found») и p3 (деление денег, обращение к несуществующему ключу массива). Сделаю скидку: при температуре 0 повторы почти одинаковые, так что это не 42 независимых опыта, и выборка в целом небольшая.

Лимит рассуждений задаётся параметром запроса reasoning_budget_tokens. На этой сборке llama-server он поддерживается: когда бюджет кончается, сервер принудительно закрывает блок рассуждений.

Помогает ли MTP качеству

Скорость он точно поднимает. Сравнение с MTP и без я делал на Q3 той же модели: 49 против 39 токенов в секунду на 8K и 44 против 34 на 32K. На Q4 черновик принимался примерно в двух случаях из трёх (291–298 из 423–440).

А вот про качество честно: не знаю. MTP в этой команде включён, и все цифры выше сняты с ним. Но отдельного прогона того же Q4 без MTP у меня нет, поэтому приписывать ему 44 из 45 я не могу.

То же с обратным выводом. На другом движке, Strata, я гонял ISTA Coder IQ1_M с MTP и без, но условия там отличались: окно, KV-кэш и тип черновиков. Сказать по тем замерам, что «MTP ухудшил PHP», тоже нельзя.

А что было с Q3

До Q4 я сидел на UD-Q3_K_XL. 7 ноября на 88 слотах она набрала 43 из 45 по PHP и выдавала 37,5 токена в секунду на 102 379 токенах контекста. 8 ноября 88 слотов уже не влезали (рабочий стол занял больше видеопамяти), и Realworld я гонял на 72 слотах: 36 правильно, 3 неверно и 3 оборвано по лимиту. Ошибки у Q3 и Q4 почти одни и те же: p3 обе провалили во всех трёх повторах. Разница только в m2: Q3 не уложилась в лимит, а Q4 ответила неверно. 8 ноября я удалил файл Q3: на диске кончилось место.

Кому это подойдёт

Если у вас RTX 3060 на 12 ГБ и 32 ГБ оперативки, а нужен локальный помощник по коду с контекстом порядка 100 тысяч токенов, эта связка рабочая. Даже на почти заполненном окне ответ пишется со скоростью около 36 токенов в секунду, с этим вполне можно работать в диалоге.

Держите в голове два ограничения. Все мои замеры — это «один запрос, один ответ», а не агент, который сам гоняет инструменты по кругу, так что про агентную работу эти цифры ничего не говорят. И длинный контекст стоит своего: на 100K модель заметно медленнее, чем на коротком запросе.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *