Запуск инференса LLM в продакшене сильно отличается от обучения моделей. Если обучение — это пакетная и предсказуемая задача, то инференс зависит от реального пользовательского спроса. Такой спрос часто бывает всплескообразным, его сложно предугадать, и пользователи не прощают задержек или простоя.
Это значит, что система должна быстро масштабироваться при всплесках трафика и уменьшаться до нуля в периоды простоя, чтобы экономить ресурсы. Такая эластичность — основа эффективности.
Однако многие организации относятся к инференсу как к обучению: заранее резервируют фиксированную мощность GPU на длительный срок. Это приводит к:
- Избыточное резервирование: простаивающие GPU, высокие расходы на простой.
- Недостаточное резервирование: потеря запросов, всплески задержек и плохой пользовательский опыт.
- Негибкий бюджет: жёсткие траты, не соответствующие реальному использованию.
Почему serverless — не панацея#
Проблема масштабирования кажется знакомой: её вроде бы решили serverless-платформы. AWS Lambda, например, легко масштабируется под спрос, но serverless плохо подходит для AI-нагрузок. Причины:
- Нет поддержки GPU: большинство serverless-платформ не поддерживают GPU. Это не просто техническая недоработка, а архитектурная и практическая особенность.
- GPU сложно “нарезать”: GPU мощные и параллельные, но не так гибки, как CPU, для одновременного инференса разных моделей.
- Высокая стоимость простаивающих GPU: GPU — как спорткары в мире вычислений: отличны для специфических задач, но дороги в обслуживании, особенно если не используются постоянно.
Проблема холодного старта#
Инфраструктура для инференса должна быстро масштабироваться, контролировать расходы и оставаться производительной. Главная сложность — холодный старт.
В случае деплоя LLM в контейнерах холодный старт возникает, когда узел Kubernetes впервые запускает нужный деплоймент. В этом случае образ контейнера не закэширован локально, и все слои образа нужно скачивать и инициализировать с нуля.
Эта проблема проявляется на трёх этапах:
Выделение облачных ресурсов: время, за которое облачный провайдер выделяет новую машину и подключает её к кластеру Kubernetes. В зависимости от типа и доступности инстанса это может занять от 30 секунд до нескольких минут, а для востребованных GPU (Nvidia A100, H100) — даже часы.
Скачивание образа контейнера: LLM-образы намного больше и сложнее обычных Python-образов из-за множества зависимостей и кастомных библиотек. Несмотря на обещания облачных провайдеров о многогигабитных скоростях, реальная загрузка часто медленнее. В итоге скачивание образа может занять 3–5 минут.
Загрузка модели: время загрузки зависит от размера модели. LLM задерживают запуск из-за миллиардов параметров. Основные узкие места:
- Медленная загрузка из model hub: такие платформы, как Hugging Face, не оптимизированы для многопоточных загрузок, поэтому скачивание больших файлов занимает много времени.
- Последовательный поток данных: файлы модели проходят несколько этапов: удалённое хранилище → локальный диск → память → GPU. Почти нет параллелизма между этапами. Каждый шаг добавляет задержку, особенно для больших файлов, которые сложно кэшировать или стримить.
- Нет стриминга по требованию: файлы модели должны быть полностью скачаны и записаны на диск до начала инференса. Это добавляет операции ввода-вывода и задерживает запуск.
Каждый этап холодного старта требует своих стратегий для минимизации задержек. Подробнее о решении этой проблемы в BentoML: 25x быстрее холодный старт LLM на Kubernetes.
Метрики масштабирования#
Масштабирование инфраструктуры для инференса LLM — это не просто реакция на нагрузку. Важно выбрать правильные метрики для эффективного, отзывчивого и экономичного масштабирования.
- Загрузка CPU. Простая метрика с понятными порогами, но не отражает реальную нагрузку для Python-задач. GIL ограничивает параллелизм на CPU, особенно на многопроцессорных машинах, поэтому метрика вводит в заблуждение.
- Загрузка GPU. Теоретически релевантная метрика, но на практике неточная. Инструменты вроде
nvmlсчитают GPU “загруженным”, если хоть один kernel запустился в окне выборки — даже на мгновение. Это не учитывает батчинг и реальную пропускную способность, что приводит к преждевременному масштабированию или ложному ощущению достаточной мощности. - QPS (запросы в секунду). Популярная метрика для веб-сервисов, но мало полезна для инференса LLM. Генеративные запросы сильно различаются по размеру и вычислительной сложности, зависят от длины входа и числа генерируемых токенов. Поэтому QPS нестабильна и её сложно использовать для автоскейлинга.
- Конкурентность. Эта метрика отражает число активных запросов (в очереди или в обработке) и идеально подходит для оценки нагрузки. Её легко настроить по размеру батча, она напрямую связана с реальными требованиями системы и позволяет точно масштабировать. Но для работы с конкурентностью нужна поддержка со стороны сервисного фреймворка, чтобы автоматически собирать метрику и использовать её как сигнал для масштабирования на платформе деплоя.
