Дезагрегация prefill и decode в SGLang: архитектура и руководство по развертыванию
Последняя проверка: 16 октября 2026 года. Флаги SGLang и поддерживаемые комбинации функций быстро меняются; перед применением этого руководства в production закрепите протестированный образ или коммит SGLang.
Дезагрегация prefill и decode в SGLang разделяет две принципиально разные задачи в обслуживании LLM: обработка промптов выполняется пулом prefill, а генерация токенов — пулом decode. Пулы обмениваются KV-кешем запроса, а маршрутизатор предоставляет клиенту единую конечную точку инференса.
Такое разделение может защитить задержку между токенами при поступлении длинных промптов и позволяет масштабировать вычислительно ёмкую capacity prefill иначе, чем ограниченную памятью capacity decode. Оно также добавляет путь передачи данных, ещё одну границу планировщика и более широкую поверхность совместимости. Рассматривайте его как архитектуру обслуживания, требующую измерений, а не как переключатель, который автоматически ускоряет любую нагрузку.
В этом руководстве объясняются архитектура дезагрегации prefill и decode в SGLang, минимальная схема развертывания, необходимые измерения и условия, при которых развертывание следует остановить.
Краткий ответ: когда дезагрегация PD оправдывает свою сложность
В документации SGLang prefill описывается как вычислительно интенсивная фаза, а decode — как интенсивная по KV-кешу и памяти. В едином планировщике входящая работа prefill может прерывать работу decode; при data-parallel attention разные воркеры также могут быть несбалансированы между этими двумя фазами. Дезагрегация PD разделяет эти фазы, чтобы каждую из них можно было планировать и обеспечивать ресурсами независимо. Документация SGLang по PD является источником истины о текущих поддерживаемых комбинациях.
| Сигнал нагрузки | Является ли дезагрегация prefill и decode в SGLang хорошим кандидатом? | Почему |
|---|---|---|
| Длинные или сильно различающиеся промпты, при этом пользователи чувствительны к плавности стриминга | Часто | Длинные prefill с меньшей вероятностью прервут активный пул decode. |
| Давление на память при decode существенно отличается от давления на вычисления при обработке промптов | Часто | Можно задавать размер пулов и ограничения конкурентности в соответствии с их фактическим узким местом. |
| Многоузловое GPU-развертывание уже имеет проверенную низколатентную инфраструктуру передачи KV | Часто | Дополнительная граница передачи данных операционно реалистична. |
| Один небольшой GPU-сервер, короткие однотипные промпты или низкий трафик | Обычно не в первую очередь | Единый сервер проще и может избежать накладных расходов на передачу. |
| Нагрузка, зависящая от локальной для процесса истории ответов или встроенных серверных инструментов | Нет, пока не проверено | Текущая документация PD перечисляет stateful-процессы Response API и встроенные инструменты среди неподдерживаемых сценариев. |
Решение заключается не в том, что «prefill быстрый, decode медленный». Вопрос в том, улучшает ли изоляция их очередей и аппаратных ограничений важную для вас пользовательскую метрику — обычно время до первого токена (TTFT), задержку между токенами (ITL), хвостовую задержку или число завершённых запросов при фиксированном бюджете capacity.
Как работает дезагрегация prefill и decode в SGLang
Топология SGLang PD включает три логические роли:
- Маршрутизатор: получает клиентский запрос, выбирает путь prefill и decode и передаёт объединённый ответ клиенту в потоковом режиме.
- Воркеры prefill: токенизируют и обрабатывают полный промпт, затем создают состояние KV-кеша, необходимое для продолжения генерации.
- Воркеры decode: получают это состояние KV и генерируют выходные токены до завершения запроса.
Передача состояния — ключевая часть. Воркер prefill не отправляет текст новому декодеру, заставляя его повторно обработать промпт. Он передаёт состояние KV-кеша, чтобы decode мог продолжить работу из того же контекста attention. В настоящее время SGLang документирует Mooncake и NIXL как движки передачи PD; выбирайте транспорт и сетевой путь, которые действительно поддерживаются закреплённой вами версией и оборудованием.
client
│
▼
PD router ──► prefill pool ──► KV-cache transfer ──► decode pool ──► streamed tokens
compute-heavy fabric memory-sensitive
В многоузловом кластере каждая роль может иметь собственное число реплик, конфигурацию GPU, лимит очереди, политику автоскейлинга и бюджет отказов. Это полезно только в том случае, если маршрутизатор и инфраструктура передачи KV рассматриваются как production-зависимости, а не как невидимый связующий слой.
Перед развертыванием: пять проверок, предотвращающих вводящие в заблуждение результаты
1. Закрепите точный релиз SGLang и конфигурацию модели
Используйте один и тот же протестированный образ или коммит SGLang для маршрутизатора, воркеров prefill и воркеров decode. Явно указывайте в манифестах ревизию модели, токенизатор, квантизацию, backend attention, стратегию параллелизма и флаги, специфичные для модели. Команда, работавшая в одной версии, в другой может быть недействительной или иметь иную семантику.
2. Проверьте путь передачи KV до масштабирования трафика
PD — это архитектура плоскости данных. Прежде чем интерпретировать задержку модели, проверьте сопоставление NIC или межсоединений, доступ контейнера к устройствам, ограничения хоста и бэкенд передачи. Для развертываний с Mooncake может потребоваться настройка InfiniBand/RDMA; в документации SGLang также описан выбор бэкенда NIXL для совместимой инфраструктуры. Не делайте вывод, что быстрый путь коллективной коммуникации автоматически подтверждает исправность пути передачи KV.
3. Создайте базовый уровень для единого сервера
Используйте одинаковые модель, промпты, длины генерации, сочетание уровней конкурентности, настройки семплирования и аппаратный бюджет для базового теста и теста PD. Измеряйте как минимум p50/p95 TTFT, p50/p95 ITL, пропускную способность запросов, поведение при отмене и частоту ошибок. Само по себе более высокое значение загрузки GPU не является результатом обслуживания.
4. Определите границы ролей в планировщике
Сделайте pod'ы, сервисы, журналы и оповещения prefill и decode независимо адресуемыми. Если вы не можете определить, какая роль стоит в очереди, исчерпала KV-ёмкость или ожидает передачу, такую архитектуру будет сложнее эксплуатировать, чем единый парк.
5. Изучите текущие ограничения совместимости, а не только блок быстрого старта
Документация по дезагрегации prefill и decode в SGLang содержит ограничения для определённых политик и рабочих процессов с состоянием. Например, документированная политика выделения decode prefill_complete имеет более узкие границы поддержки, чем политика по умолчанию. Проверяйте каждую комбинацию расширенных функций в промежуточном запуске, прежде чем включать её в обещание доступности.
Минимальное развертывание дезагрегации prefill и decode в SGLang
Начните с одного worker'а prefill, одного worker'а decode и одного маршрутизатора на хосте с двумя GPU. Это тест функциональной приемки, а не утверждение, что две GPU являются конфигурацией для production. Следующий пример NIXL соответствует текущему upstream-паттерну для одного узла; используйте точный синтаксис команд из документации для закреплённой версии SGLang.
# GPU 0: prefill role
python -m sglang.launch_server \
--model-path meta-llama/Llama-3.1-8B-Instruct \
--disaggregation-mode prefill \
--disaggregation-transfer-backend nixl \
--port 30000
# GPU 1: decode role
python -m sglang.launch_server \
--model-path meta-llama/Llama-3.1-8B-Instruct \
--disaggregation-mode decode \
--disaggregation-transfer-backend nixl \
--base-gpu-id 1 \
--port 30001
# Client-facing PD router
python -m sglang_router.launch_router \
--pd-disaggregation \
--prefill http://127.0.0.1:30000 \
--decode http://127.0.0.1:30001 \
--host 0.0.0.0 \
--port 8000
Отправьте короткий запрос через маршрутизатор, а не напрямую любому из worker'ов:
curl http://127.0.0.1:8000/v1/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "meta-llama/Llama-3.1-8B-Instruct",
"prompt": "Explain why KV-cache handoff matters in one sentence.",
"max_tokens": 64
}'
Успех означает больше, чем получение текста. Убедитесь, что маршрутизатор выбрал обе роли, передача KV завершилась, потоковая передача работает корректно и каждый процесс сообщает об ожидаемых настройках модели и совместимости. Сохраняйте это небольшое развертывание дезагрегации prefill и decode в SGLang в CI или pre-production-среде, чтобы обновление не нарушило незаметно путь PD.
Для развертывания Mooncake используйте актуальное руководство SGLang по PD для требуемой установки движка передачи и настройки IB-устройства. Не копируйте переменные окружения Mooncake из другого транспорта, облака или выпуска SGLang.
Переход от одной пары к production-топологии
Когда базовая пара работает корректно, масштабируйте каждую роль на основе данных об очередях и ресурсах, а не предполагаемого соотношения 1:1.
| Уровень | Масштабируйте на основе этого наблюдения | Практическое действие |
|---|---|---|
| Пул prefill | Растёт очередь промптов, насыщаются вычисления prefill или увеличиваются хвостовые значения TTFT | Добавьте реплики prefill или измените конфигурацию GPU для prefill после контролируемого теста. |
| Пул decode | Активные последовательности исчерпывают KV-ёмкость, увеличиваются хвостовые значения ITL или ожидание допуска decode | Добавьте реплики decode, снизьте конкурентность или увеличьте память на worker только после проверки занимаемого моделью объёма. |
| Сеть передачи KV | Время передачи или ошибки передачи доминируют на временной шкале запроса | Проверьте сопоставление устройств, бэкенд, состояние сети и топологическую локальность, прежде чем добавлять реплики модели. |
| Маршрутизатор | Появляется частая смена неисправных worker'ов, неравномерные очереди или задержка маршрутизации | Используйте production-топологию маршрутизатора и политику, поддерживаемые вашей версией SGLang. |
Для многоузловых паттернов SGLang публикует отдельные примеры запуска prefill и decode для развертываний класса DeepSeek, включая специфичные для ролей аргументы распределённой инициализации и параллелизма. Эти примеры — полезный шаблон, но для модели, оборудования и версии SGLang всё равно необходим собственный приемочный тест. Перед адаптацией манифеста кластера ознакомьтесь с upstream-примерами многоузлового PD.
Если Kubernetes управляет жизненным циклом, назначьте prefill и decode отдельные метки, сервисы, бюджеты допустимых нарушений, дашборды и пробы готовности. Более широкие требования к кластеру — предоставление GPU, очереди, хранилище, сеть и наблюдаемость — рассмотрены в нашем руководстве по GPU-кластеру Kubernetes.
Метрики для дезагрегации prefill и decode в SGLang
Дезагрегация prefill и decode в SGLang должна улучшать выбранный результат рабочей нагрузки, а не просто создавать другой график использования ресурсов. Инструментируйте временную шкалу запроса, выделяя отдельные интервалы prefill, передачи, допуска decode и генерации.
| Метрика | Что показывает | Анализируйте вместе с |
|---|---|---|
| TTFT, p50 и p95 | Постановка промптов в очередь, выполнение prefill и передача | Группами по длине промпта и глубиной очереди prefill |
| ITL, p50 и p95 | Темп выдачи токенов после начала генерации | Активными последовательностями decode и заполненностью KV для decode |
| Длительность и ошибки KV-передачи | Является ли передача узким местом или источником сбоев | Пропускной способностью сети, повторами, состоянием NIC и логами backend |
| Возраст очереди prefill/decode | Неверно ли выбрано соотношение пулов | Числом реплик для каждой роли и лимитами параллелизма |
| Завершённые запросы в секунду | Полезная ёмкость при фактическом миксе | Долей ошибок, долей отмен и SLO задержки |
| Использование GPU compute, HBM и CPU хоста | Вспомогательная диагностика, а не целевой результат | Четырьмя указанными выше длительностями этапов запроса |
Запустите два набора тестов. В одном должен использоваться ожидаемый сегодня микс трафика; другой должен намеренно включать длинные промпты, переменную длину генерации, отмены и всплески нагрузки. PD может выглядеть превосходно на среднем синтетическом промпте, но не выполнять своё фактическое назначение при несбалансированном производственном миксе.
Политика выделения ресурсов для decode: целевое управление, а не стандартный приём настройки
По умолчанию SGLang документирует поведение выделения ресурсов для decode early: целевые слоты KV резервируются до завершения prefill. Поэтому длительные prefill могут удерживать ёмкость decode, пока сторона decode ожидает данные KV.
Документированная альтернатива:
--disaggregation-decode-allocation-policy prefill_complete
При prefill_complete SGLang откладывает выделение ресурсов на целевой стороне до готовности prefill. Это может помочь, когда длинные промпты конкурируют с активным трафиком decode за целевую KV-ёмкость, но также меняет характер перекрытия операций и границы поддержки. В документации upstream указано, что политику следует задавать как для prefill, так и для decode, и перечислено несколько несовместимых комбинаций. Рассматривайте её как контролируемый эксперимент с критериями отката, а не как универсальную оптимизацию.
Распространённые режимы отказа и следующая самая быстрая проверка
| Симптом | Вероятная граница для проверки | Быстрая следующая проверка |
|---|---|---|
| Маршрутизатор принимает запросы, но токены не возвращаются | Доступность воркеров или сбой передачи между ролями | Проверьте логи маршрутизатора, состояние воркеров и одну трассировку от prefill до decode. |
| Время ожидания decode растёт, хотя prefill работает штатно | Допуск decode или давление на целевой KV | Проверьте активные последовательности, заполненность KV и политику выделения ресурсов, прежде чем произвольно добавлять ёмкость prefill. |
| TTFT улучшается, но ITL ухудшается | Узкое место в пуле decode или KV-передаче | Сравните возраст очереди decode, длительность передачи и число активных последовательностей с объединённой базовой конфигурацией. |
| Трафик между несколькими узлами периодически зависает или повторяется | Сетевая фабрика, сопоставление устройств или несогласованная конфигурация воркеров | Проверьте точную сборку SGLang, backend передачи, сопоставление NIC и манифесты ролей на каждом узле. |
| Расширенная функция работает в объединённом режиме, но не работает в PD | Неподдерживаемая комбинация функций | Изучите текущий раздел совместимости PD и воспроизведите проблему в наименьшей поддерживаемой топологии. |
| Использование GPU растёт, но пользовательская задержка не улучшается | Оптимизация была направлена не на тот этап | Вернитесь к TTFT, ITL, возрасту очереди, ошибкам и пропускной способности завершённой работы. |
Развёртывание дезагрегации prefill и decode в SGLang должно быть обратимым. Сохраняйте маршрут объединённого обслуживания или заведомо рабочую ревизию развёртывания, пока конфигурация PD не достигнет заданных порогов задержки и надёжности для важного микса рабочих нагрузок.
Безопасная последовательность развёртывания
- Базовая линия: Зафиксируйте бенчмарк объединённого SGLang с приближенными к производственным промптами, выводами, параллелизмом и сценариями сбоев.
- Одна пара: Запустите один воркер prefill, один воркер decode и маршрутизатор; пройдите проверки функциональности, потоковой передачи, отмены и перезапуска.
- Видимость ролей: Разделите логи, дашборды, оповещения и лимиты ёмкости по маршрутизатору, prefill, передаче и decode.
- Контролируемая нагрузка: Сравните PD с базовой линией по группам длины промптов и длины вывода, а не только по среднему значению.
- Масштабируйте по одному ограничению за раз: Корректируйте размер пула, конфигурацию GPU, параллелизм или конфигурацию передачи в отдельных экспериментах.
- Канареечное развёртывание и откат: Направьте ограниченную долю трафика, определите порог задержки/ошибок для отката и сохраните последнюю работоспособную конфигурацию.
Эта последовательность превращает дезагрегацию prefill и decode в SGLang PD из многообещающей архитектурной схемы в изменение, которое можно протестировать в рабочей среде.
Часто задаваемые вопросы
Всегда ли дезагрегация PD увеличивает пропускную способность?
Нет. Она может улучшить рабочую нагрузку, в которой ограничением является конкуренция между prefill и decode, но также добавляет передачу KV, планирование маршрутизатора и операционные накладные расходы. Протестируйте её относительно единой базовой конфигурации, используя тот же профиль трафика и бюджет мощности.
Выполняется ли prefill на другой модели, чем decode?
Нет. Эти роли продолжают один логический запрос. Сохраняйте согласованность протестированных модели, токенизатора, ревизии, квантизации и конфигурации обслуживания в обеих частях, если документация upstream явно не поддерживает другую схему.
Какой backend передачи данных следует использовать?
Используйте backend, поддерживаемый закреплённой версией SGLang и проверенный для вашей фактической инфраструктуры. Текущая документация SGLang описывает Mooncake и NIXL, но правильный выбор зависит от платформы, образа контейнера, устройств и проверенной вами операционной поддержки.
Можно ли сочетать дезагрегацию prefill и decode в SGLang со всеми расширенными функциями?
Нет. Поддержка PD зависит от функций и версии. Перед сочетанием с ответами с сохранением состояния, выполнением инструментов, функциями кеша, режимами спекуляции или нестандартным поведением ролей ознакомьтесь с актуальными примечаниями upstream о совместимости.
Практический следующий шаг
Начните со среды приемочного тестирования с одной парой, зафиксируйте пороговые значения TTFT/ITL/ошибок, оправдывающие эту архитектуру, и переходите к следующему этапу только после того, как пути передачи и сбоев станут наблюдаемыми. Для смежных решений по обслуживанию сравните vLLM и SGLang, изучите спекулятивное декодирование для инференса LLM и планируйте базовый кластер Kubernetes с GPU отдельно от развертывания PD.



