Pull to refresh

Comments 39

Четыре P102-100 Qwen3.8-27B-Q5 без -sm tensor было 15-20 ток. нагрузка на GPU была 50%. С -sm tensor стало 25-33 ток. и все GPU загружаются на 100%. Отлично - теперь llama.cpp работает с картами как и vllm. Спасибо.

Можно поинтересоваться какое pci-e подключение карт и какой процессор?

У меня на 4x3060 12гб, при включении MTP сразу просадка до 6т/c на двух потоках. С выключенным 40-50т/c на двух потоках (суммарно).
А на одном потоке включенный MTP подымает примерно с 30 до 40т/c.

У меня на 2×3090 та же связка ведёт себя иначе: -sm layer + MTP + --parallel 2 даёт 36.3 + 36.3 ток/с, без всякого обвала. Так что MTP с несколькими слотами сам по себе не сломан — у вас что-то конкретное, и, судя по цифрам, это не деградация, а падение с обрыва. 8-кратный провал — почерк не «стало неэффективно», а «работа уехала туда, где её быть не должно». Если не жалко, покажите вывод nvidia-smi --query-gpu=pcie.link.width.current --format=csv.

Большое спасибо, Добрый человек. Половину из этого уже накопал, стала стабильно работать на трёх mi50 32g, вторую половину сейчас проверю. Особенно надежда на квантование кэша черновика и sm tensor

Тоже страдаю MI50. Если у вас есть какие наработки, по увеличению скорости инференсов на этих музейных экспонатах, поделитесь пожалуйста. 🙂

Не понял, вот это -c 524288 --parallel 2зачем?

Для обработки (генерации ответов) от 2-х параллельных запросов.

Дам подробный ответ. -c — это суммарный пул KV на весь сервер, а не длина одного запроса. llama.cpp делит его на слоты, поэтому -c 524288 --parallel 2 = два независимых слота по 262 144 токена, ровно родной контекст модели. Обратная сторона: если написать -c 262144 --parallel 2, каждый слот получит по 131 072, и длинные промпты начнёт обрезать — при том что в аргументах вроде бы стоит полный контекст модели. Проверяется по строке при старте:

srv load_model: initializing, n_slots = 2, n_ctx_slot = 262144, kv_unified = 'false'

Два слота нужны, чтобы второй запрос не ждал в очереди, пока идёт первый: агент и редактор ходят в один эндпоинт одновременно. Цена — скорость каждого: 47.4 + 50.3 ток/с при двух занятых слотах против 74.8 в одиночку, то есть суммарная пропускная способность растёт, а отдельный ответ идёт медленнее.

Я в работе использую связку из скилов и субагентов - и мне это важно. Обычно я ставлю 4 слота, т.е. контекст на 1М в 4 параллели - 4 слота по 256к. С одной стороны это мой кейс, и мой конфиг - для всех читателей это карта куда идти за результатом. С другой - конкретно эти параметры можно было бы более подробно описать. В этом комментарии и исправляюсь.

Можно использовать unified kv cache (--kv-unified), чтобы был общий пул кэша для всех запросов.

Проверил на стенде — спасибо.

Флаг работает как обещано: --kv-unified -c 262144 --parallel 2 освобождает 8.8 ГиБ (42.6 → 33.8), needle на 240K те же 3/3, скорость просела на 2%. Но есть цена, которую видно только отдельным тестом.

Общий пул вытесняет кэши слотов. Даю слоту 0 контекст на 143K, слоту 1 другой на 143K, возвращаюсь к слоту 0:

unified : возврат 143 562 ток, 163.6 с статика : возврат 261 ток, 1.8 с

Два контекста по 143K — это 286K, пул 262 144, вместе не помещаются, первый вытесняется. --cache-idle-slots не спасает, это честный пересчёт с нуля. Разница в 91 раз.

Мне слоты нужны как независимые контексты со своими живущими кэшами, поэтому остаюсь на статической нарезке. Правило: unified выигрывает, когда слотов много, а сумма их активных контекстов заведомо меньше пула. Как только сумма превышает пул, начинается вытеснение.

Два побочных наблюдения. С unified n_ctx_slot упирается в родной контекст модели, а не в -c — поэтому unified с -c 524288 бессмыслен, памяти больше, скорость ниже, возможности те же. И unified включён по умолчанию, если --parallel не задан явно, так что часть читателей уже на нём.

Вы используете 2 параллельных запроса в однопользовательском режиме правильно понимаю? То есть модель подключает субагента и тот работает параллельно основной задаче?

Смысл в слотах - это кэши. Если агент+субагент, то это 2 независимых контекста со своими кэшами. Они могут работать и параллельно и последовательно, главное - у них свои кэши.

На CMP 50HX 20GB Qwen3.8-27B Heretic IQ4_XS + MTP n=2 + Vision у меня завелась на 2×64K контекста. Prefill: ~558 tok/s на 5K, ~531 на 20K, ~427 на 60K. TG в коротких тестах: ~45/32/28 tok/s соответственно. MTP acceptance ~67%

Кажется, что acceptance слишком низкий. Может поднять –spec-draft-p-min повыше?

Это был короткий тест. Конечно имеет смысл поиграть параметрами

Хочу тоже поделиться наблюдениями. Очень похоже что качество действительно зависит от сборки. Unsloth зарекомендовал себя,но похоже что иногда они переигрывают. Недавно заиорочился тоже с проверкой скорости, но было интереснее именно математически рассчитать - получился своебразный калькулятор +- показывающий то что у меня на выходе. Но для чистоты эксперимента и прогонов я взял модель бартовски обратил внимание в метаданных что там 33 слоя у квена, а у анслоф 32...

В общем погонял модели и удивидся что мой промпт на 4b модель смогла сделать играбельную игру, в то время как на сборке unsloth такое выходило раз в 10-20 прогонов. Надо бы еще раз погонять...

Пожалуй напишу небольшую статью про то как я это делал, и может вы сделаете что-то похожее... Я сделал букмарклет который на странице модели посвечивает теоретическую скорость на моем железе. Кстати обратил внимание что если залогиниться на hf можно добавить свое железо и он тоже может выдать какие-то цифры, но пока не проверял

Добрый день!

Очень ждём статью.

Уже есть) https://habr.com/ru/articles/1076284/

Правда, практической пользы оказалось не так много, но вдруг кого-то натолкнет на какие-то мысли)

У меня Q6_K_M на 200к контексте отлично влезли с MTP головой, 100т/с на одной 5090. 256к влезло, но скорость падает до 1т/с после достижения 210к, так что 200 поставил.

Если кому надо, вот команда которую использую:

llama-server.exe -m "d:\llamacpp_models\Qwen3.8-27B-UD-Q6_K_M.gguf" --port 11434 --host 0.0.0.0 --ctx-size 200000 --temp 1.0 --top-p 0.95 --top-k 20 --min-p 0.0 --jinja --threads 24 -ngl 99 --parallel 1 --timeout 60000 -cram -1 -fa on -ctk turbo4 -ctv turbo3 -ctkd q8_0 -ctvd q8_0 --spec-type draft-mtp --spec-draft-n-max 3 --kv-unified --chat-template-kwargs "{\"reasoning_effort\":\"xhigh\"}" --reasoning-preserve -ngld all -md d:\llamacpp_models\mtp-Qwen3.8-27B-Q4_0.gguf

Там собран под железо (5090 - sm120) форк ламы с турбоквантом свежайший из гита.

Кванты от unsloth.

На этом конфиге через него за неделю около 100м токенов прогнал.

а мне как раз интересно было сколько можно выжать на 5090.

а откуда взялась модель -md d:\llamacpp_models\mtp-Qwen3.8-27B-Q4_0.gguf , она отдельно скачивается?
Это ведь модель только с MTP слоем?

У Qwen3.8-27B голова MTP уже лежит внутри обычных весов — я проверил у двух разных сборок, в unsloth Qwen3.8-27B-Q8_0.gguf и в bartowski Q6_K_L, тензоры blk.64.nextn.* на месте у обеих. Поэтому --spec-type draft-mtp работает сам, без -md.

Проверить свою сборку проще всего запуском: уберите -md и оставьте --spec-type draft-mtp. Заработало — голова внутри. Если хочется заглянуть в файл, head -c 20000000 model.gguf | strings | grep blk.64.nextn покажет её, не читая все 20 гигабайт.

Отдельный файл нужен там, где головы внутри нет. У Qwen3.6, например, unsloth выкладывал MTP отдельными сборками -MTP-GGUF.

У меня один товарищ тестировал NInfer фреймворк, и у него на 5090 до 700т/с выдает. Не пробовали такое?

5090 + 3090 через oculink (PCIe x4 4.0) все с MTP

-sm layer

Prompt processing speed @42K: 2161.54 tokens/s

Generation speed: 53.07 t/s

-sm tensor

Prompt processing speed @42K: 1120.00 tokens/s

Generation speed: 70.46 t/s

Как запускаю:
llama-server -m “\unsloth\Qwen3.8-27B-GGUF\Qwen3.8-27B-UD-Q8_K_XL.gguf” --mmproj “\unsloth\Qwen3.8-27B-GGUF\mmproj-F16.gguf” -ngl 99 -fa on -np 2 -ts 36,24 -dev CUDA0,CUDA1 --main-gpu 0 -c 262141 -b 2048 -ub 512 -ctk f16 -ctv f16 --spec-type draft-mtp --reasoning-budget -1 --reasoning-preserve --host 0.0.0.0 --temp 1.0 --top-p 0.95 --top-k 20 --min-p 0 --kv-unified -sm tensor

Учитывая что qwen 3.8 очень много думает, то пожертвовать скоростью обработки промпта можно ради прибавке в скорости генерации

Даже как-то обидно такие цифры видеть. 3090 просто режет 5090. Скорость обработки у меня тоже просела, но не сильно −20% на 40K, −11% на 130K, −3% на 240K - это я уже писал в статье.

А что делать, я покупал 5090 за 220, сейчас можно купить от 300 на авито, 3090 тоже покупал за 65, сейчас около 90 живая.

Но тут думаю еще влияет узкий канал PCIe x4 4.0, так как если запускать deepseek v4 flash, то там падение скорости обработки промпта в 3 раза и прироста по скорости генерации почти нет.

Моя нейросеть вашей передаёт привет. По ссылке посмотрел. Эксперименты там интересные, жаль что пока не практичные. Будем наблюдать.

А тем временем пара 2080ти с нвлинк в ку8 даёт 100 т/с на форке вллм. Пара 3090 должна давать соответственно 130+.

Почему 32 — это не «упёрлись в железо»

Opus detected. Человек к статье не прикасался.

Удивляет тут наличие пережитков прошлого, с обязательным желанием делиться своим мнением. Материал либо полезен, либо нет. А написан он пером от руки, или на печатной машинке - это не должно вообще никого волновать.

Спасибо за статью. Имею связку 5070ti (pcie5x16) и 5060ti (pcie4x4).
На пустом контексте скорость генерации ~ 27/45 (без mtp, с mtp, около 70% прироста), но на 100к опускается до 24/27 (около 13% прироста). Принятие черновика нормальное - "draft acceptance = 0.77460 ( 1677 accepted / 2165 generated), mean len = 2.73". Квант UD-Q5_K_X.
Подскажите, это нормальное поведение на большой длине контекста или я что-то недокрутил?
Конфиг такой:
%LLAMA% -m %MODEL% ^
–host 0.0.0.0 --port 8033 -np 1 ^
-fa on -ctk q8_0 -ctv q8_0 ^ -ngl 99 --fit off ^
-b 2048 -ub 512 ^ –no-mmap --no-warmup ^
–temp 1.0 --top-k 20 --top-p 0.95 --min-p 0.0 ^
–presence-penalty 0.0 --repeat-penalty 1.0 ^
–jinja --reasoning-format deepseek ^
–chat-template-kwargs “{“reasoning_effort”:“low”}” ^
–spec-type draft-mtp --spec-draft-n-max 3 --spec-draft-p-min 0.7 --cache-type-k-draft q4_0 --cache-type-v-draft q4_0 ^
–split-mode tensor -c 110000 ^
-lv 4 --timeout 900 --no-mmproj


UPD удалил --spec-draft-p-min 0.7, количество черновиков выставил в 4 получил 32 t/s (33% прироста), хотя принятие черновика упало довольно сильно (draft acceptance = 0.39764 ( 808 accepted / 2032 generated), mean len = 2.59)

Померил у себя ровно этот вопрос — пара 3090, -sm tensor, Q6_K_L, KV q4_0, тот же промпт про quicksort, по 5-6 полных прогонов на точку.

Без MTP: 48.1 ток/с на пустом контексте, 33.9 на 91K. С MTP при --spec-draft-n-max 3: 86.9 и 61.0.

Множитель от MTP получается 1.81 на пустом и 1.80 на 91K. То есть он не тает вообще: сам контекст срезает скорость на 30%, но срезает одинаково обе конфигурации. Так что 70% → 13% — это не «нормальное поведение MTP на длине», у вас упирается что-то конкретное.

Самое полезное в ваших числах вот что. Без MTP вы теряете 27 → 24, всего 11 процентов, у меня на той же дистанции 30. Значит с памятью и вниманием у вас всё хорошо, проседает именно спекулятивный путь. Это сильно сужает круг поиска.

Что проверил бы, по убыванию ожидаемой отдачи.

Первое — -ctk q8_0 -ctv q8_0. На 110K это вдвое больше байт кэша, чем нужно, а верификация вычитывает кэш на каждом шаге. У меня q4_0, и needle-тест на 240K даёт 3/3, то есть качество на этом кванте не теряется. Заодно освободится пара гигабайт.

Второе — --spec-draft-p-min 0.7, который вы уже сняли и получили плюс 19 процентов. Это не случайность, порог стоит убрать совсем, я его не передаю. И не ориентируйтесь на acceptance как на целевую метрику: с порогом черновик пишет только то, в чём уверен, поэтому доля принятых высокая, а самих черновиков мало. У меня --spec-draft-n-max 2/3/4/6 даёт 52.8/57.3/57.6/54.3 ток/с, при этом принятие падает с 59 до 39 процентов. Оптимизируется ток/с, а не проценты.

Третье: это гипотеза, а не замер. У вас 5070 Ti и 5060 Ti — 896 и 448 ГБ/с, ровно вдвое. При -sm tensor слой считают обе карты и ждут медленную, а перекос не выправить: -ts под тензорным сплитом не работает, llama.cpp пишет llama_params_fit is not implemented for SPLIT_MODE_TENSOR. На бумаге тензорный сплит должен выигрывать даже при таком перекосе, так что я не говорю «переключайтесь». Но рекомендация из статьи измерена на двух одинаковых картах, обе на x16, а ваша пара за её границами — прогнать -sm layer с -ts в пользу 5070 Ti и сравнить - это проще, чем гадать.

Спасибо!

Проверил третью гипотезу, генерация выходит медленнее чем в режиме tensor процентов на 20, хотя и префил резко подскочил с 800-900 до 1400-1700.

Ускорение от mtp довольно сильно разнится, попробовал на том же контексте (отрывок из книги) задавать другие вопросы - прыгает от 30% до 70%, но все равно потрясающе, такой прирост ценой 1.5гб памяти.

А почему может быть такая ошибка:
gml-backend-meta.cpp:1760: GGML_ASSERT(meta_buf_ctx->bufs[i]) failed

При добавлении sm tensor? Не docker, вот команда запуска:
…\llama-server.exe -m “DeepSeek-V4-Flash-UD-Q8_K_XL-00001-of-00005.gguf” --fit off -ngl 99 --n-cpu-moe 33 --tensor-split 11,3 --no-mmap -c 32768 --model-draft “dspark-DeepSeek-V4-Flash-0731-Q8_0.gguf” --spec-type draft-dspark --spec-draft-n-max 3 -ctkd q4_0 -ctvd q4_0 -sm tensor --numa distribute --alias Deepseek-v4-flash

Sign up to leave a comment.

Articles