Как я удвоил эффективность GPU, не покупая ни одной новой карты

Прослушать статью

Прекратите переплачивать за простаивающие GPU: разделите рабочую нагрузку LLM на пулы для prompt processing и генерации. Это как дать вашему ИИ отдельные быстрые и медленные полосы.

В конце прошлого года меня привлекли к задаче планирования мощностей для глобального ритейлера, который встроил модель на 70B параметров в поиск и рекомендации товаров. Каждый поисковый запрос запускал вызов инференса. Во время праздничного трафика их кластер расходовал GPU-часов так, что cloud-финансовая команда чувствовала себя крайне неуютно. Они уже масштабировались с 24 до 48 H100, но задержки все равно росли в пиковые часы. Меня попросили ответить на простой вопрос: нужны ли 96 GPU для январской распродажи или происходит что-то другое?

Я начал с того, с чего всегда начинаю в таких проектах: с profiling. Я внедрил инструменты наблюдения в serving layer и разложил данные по утилизации на фазы инференса. Результат изменил мое представление об инфраструктуре GPU.

Во время prompt processing — фазы, когда модель читает весь пользовательский ввод параллельно, — H100 работали с вычислительной загрузкой 92%. Tensor cores были полностью насыщены. Именно такого поведения и ждешь от GPU за 30 000 долларов. Но эта фаза длилась около 200 миллисекунд на запрос. Следующая фаза, token generation, занимала от 3 до 9 секунд. В это время те же GPU падали до 30% утилизации. Вычислительные ядра простаивали, а шина памяти работала на пределе, читая attention cache.

Мы платили по ставкам H100-hour за пиковую вычислительную мощность и получали пиковую производительность примерно в 5% общего времени обработки запроса. Остальные 95% были проблемой пропускной способности памяти, замаскированной под GPU с вычислительной ценой.

Шаблон, который был у всех перед глазами

Как только я это увидел, я уже не мог развидеть. Инференс LLM — это две разные нагрузки, которые притворяются одной. Prompt processing, который в индустрии называют prefill, — это плотное умножение матриц, задействующее каждое ядро на чипе. Token generation, или decode, — это последовательное чтение из памяти, которое затрагивает лишь часть вычислительных ресурсов. Они чередуются на одном и том же оборудовании внутри одного и того же цикла планирования. Я работал с carrier-scale Kubernetes-кластерами и высокопроизводительными конвейерами данных, и я никогда не видел настолько бимодальный профиль нагрузки на таком дорогом железе.

Если бы вы строили базу данных таким образом — резервировали бы систему под пиковую запись, а потом 90% времени использовали бы сервер только для чтения, — вы бы без раздумий разделили ее на write primary и read replicas. Но большинство команд, обслуживающих LLM, пока не провели эту аналогию.

Средства мониторинга только ухудшают ситуацию. На каждой панели инференса, которую я видел, отображался один показатель «GPU utilization»: среднее значение обеих фаз, смешанное в одно число. У нашего кластера было 55%. Выглядит нормально. Никто не паникует из-за 55%. Но 55% — это среднее от 92% на несколько сотен миллисекунд и 30% на несколько секунд. Дашборды прятали бимодальное распределение за одним числом.

Исследователи из UC San Diego’s Hao AI Lab опубликовали на OSDI 2024 статью DistServe, в которой проблема была описана цифрами, почти идентичными моим данным профилирования. Их измерения на H100 показали тот же паттерн: prefill — 90–95% утилизации, decode — 20–40%. Они же предложили и решение.

Разделить работу надвое

Решение называется disaggregated inference. Вместо того чтобы запускать обе фазы на одном и том же пуле GPU, вы поднимаете два пула: один, настроенный под compute throughput для prompt processing, и другой, настроенный под memory bandwidth для token generation. Впереди ставится routing layer, который отправляет каждый запрос в нужный пул в нужный момент, а attention cache передается между ними по быстрому сетевому каналу.

Когда я впервые предложил это заказчику, он отнесся скептически. Два пула означают более высокую операционную сложность. Протокол передачи cache добавляет сетевую зависимость, которой нет в монолитном serving. Справедливые возражения. Поэтому я показал, кто уже так работает.

Perplexity построила весь свой production serving stack на disaggregated inference, используя RDMA для передачи cache. Meta использует это. LinkedIn использует это. Mistral использует это. К началу 2026 года NVIDIA выпустила orchestration framework под названием Dynamo, который рассматривает prefill и decode как первоклассные типы пулов. Open-source движки — vLLM и SGLang — оба добавили нативные режимы disaggregated serving. Red Hat и IBM Research опубликовали Kubernetes-native реализацию под названием llm-d, которая переносит эту архитектуру в стандартные рабочие процессы управления кластером.

Это не исследовательский прототип, который ждет смелого первопроходца. Это архитектура по умолчанию у компаний, которые обслуживают больше LLM-трафика, чем кто-либо на планете.

Что изменилось после разделения пулов

Мы запустили двухнедельный proof of concept. Я разделил кластер на два пула: восемь GPU выделили под prompt processing, остальные GPU — под token generation. Без нового оборудования, без нового кластера — только изменение конфигурации в serving layer и routing policy, которая отправляла каждый запрос в нужный пул в зависимости от фазы инференса. Пул для prompt processing стабильно выходил на 90–95% compute utilization, потому что занимался только этим. Никакой конкуренции token generation за слоты планирования. Никаких decode-запросов, которые простаивают, пока prefill-рывок захватывает ядра.

Больше всего удивил пул token generation. За счет batch-обработки сотен одновременных decode-запросов операции чтения из памяти удалось распределить на большее число вычислений. Утилизация полосы пропускания поднялась выше 70% — заметно лучше, чем 30%, которые мы видели, когда decode-запросы чередовались с prefill на одном и том же GPU. Общая вычислительная эффективность примерно удвоилась.

За этим последовала и экономика. Клиент тратил около 2 млн долларов в год на GPU-hours для инференса. После disaggregation он шел к сокращению этой суммы на 600–800 тыс. долларов при том же объеме запросов и тех же целевых задержках. Никакого нового оборудования не покупали. Те же GPU, тот же кластер, те же веса модели — другая архитектура.

История с задержками была не хуже. В монолитной схеме каждый раз, когда приходил новый prompt, его burst обработки тормозил активные token-generation запросы. Пользователи, которые смотрели streaming responses, видели, как текст замирает посреди предложения, пока обрабатывается чужой prompt. После разделения токенов шли ровно: без stall, вызванных prefill. P99 inter-token latency полностью выровнялась.

Есть сценарии, где это не окупается. Короткие prompt’ы короче 512 токенов с короткими ответами не создают достаточно cache, чтобы оправдать передачу по сети. Многоходовые диалоги, где 80%+ cache уже находится на decode worker после предыдущего хода, лучше обслуживать локально. А если у вас меньше дюжины GPU, накладные расходы на планирование двух пулов могут съесть всю выгоду от более высокой утилизации. Но команды, которые жалуются на дефицит GPU и счета за GPU, не работают с 4-GPU-развертываниями и prompt’ами на 512 токенов. Они используют десятки и сотни GPU в масштабе enterprise, где потери утилизации превращаются в миллионы долларов в год.

Индустрия тратит массу энергии на сторону предложения GPU: строит больше fabs, проектирует лучшие чипы, договаривается о больших cloud-контрактах. Все это важно. Но я снова и снова возвращаюсь к тому, что увидел в данных profiling. Если бы команды, которые сегодня запускают монолитный LLM inference, перешли на disaggregated serving, эффективное предложение GPU почти удвоилось бы за одну ночь. Никакого нового silicon не требуется. Инструменты уже готовы. Подтверждения уже есть в production. Не хватает только шага profiling, который делает потери видимыми.

Если вы еще не разбили утилизацию инференса по фазам, сделайте это на этой неделе. Добавьте пофазовую instrumentation в serving layer. Постройте графики prefill utilization и decode utilization отдельно за 24 часа. Если эти две линии выглядят так, будто им место на разных графиках — а так и будет, — у вас есть ответ. Вы перестанете платить за вычисления, которые не используете.

Эта статья опубликована в рамках Foundry Expert Contributor Network. Хотите присоединиться?


Материал — перевод статьи с английского.

Оригинал: How I doubled my GPU efficiency without buying a single new card