GPU-планировщик с приоритетами обошёл FIFO: загрузка кластера выросла на 33 п.п.

Команда, публикующаяся в блоге Dharma AI на платформе Hugging Face, построила «ограниченно-осведомлённый» (constraint-aware) планировщик распределения GPU и сравнила его с базовым FIFO-планировщиком на семи тестовых сценариях. Железо и нагрузка в обеих версиях были одинаковыми, менялся только порядок, в котором система принимает решения о распределении. Результат: загрузка GPU выросла до 33 процентных пунктов, а «ценность» работы кластера, суммарный результат, взвешенный по приоритету задач, выросла в каждом из семи сценариев, максимум на 105%.
Проблема в статье описана так. За место на кластере конкурируют четыре типа задач: обучение моделей, батч-инференс, квантование и инференс в реальном времени. Первые три «блочные»: раз начавшись, задача держит непрерывный блок GPU до завершения. Инференс в реальном времени устроен иначе, это эластичная нагрузка, которая растёт и падает вместе с трафиком на каждом временном шаге. FIFO решает эту конкуренцию плохо по двум причинам. Во-первых, поскольку планировщик не умеет забирать GPU у real-time-приложения в момент спада и возвращать их к пику, единственный способ гарантировать доступность, зарезервировать под приложение GPU по максимуму суточного спроса и держать их весь день; простаивающие часы никуда не деваются. Из-за этого в двух сценариях, где резерв доминирует, базовая (FIFO) загрузка держится около половины кластера: 51,6% в смешанном контрольном сценарии и 53,6% в сценарии с упором на обучение. Во-вторых, всё, что не зарезервировано, FIFO раздаёт в порядке поступления заявок, не глядя на приоритет, высокоприоритетная задача ждёт позади той, что просто пришла раньше.
В пяти состязательных сценариях аллокатор поднял загрузку с диапазона 52, 85% до диапазона 72, 88%, а взвешенную по приоритету ценность, на 24,6, 105,1%, в среднем на 52%. Сильнее всего эффект проявился в сценарии с упором на обучение на 8 GPU: загрузка выросла с 53,6% до 87,0%, а ценность увеличилась более чем вдвое, на 105% (авторы уточняют: эта цифра получена относительно одного конкретного порядка поступления заявок в FIFO, а не усреднена по разным порядкам). В тесте на масштаб, 30 задач на 64 GPU, FIFO и аллокатор показали одинаковую загрузку (44,9%) и одинаковое число завершённых задач (27 из 30), но аллокатор дал на 15,9% больше взвешенной по приоритету ценности: загрузка сама по себе не говорит о том, чего стоит выполненная работа. Отдельно авторы проверили, что выигрыш, не только эффект приоритезации: если всем задачам выставить одинаковый приоритет, аллокатор всё равно поднимает загрузку с 76,8% до 87,5%, а ценность, на 23,1%, то есть само планирование размещений на весь горизонт вперёд (а не по одной заявке за раз) уже даёт выигрыш.
Технически легальное размещение задаётся пятью ограничениями: один GPU обслуживает не более одной задачи за такт; каждая задача укладывается в свой диапазон спроса, а уже запущенная работа наследуется и удерживается; блочные задачи занимают непрерывные блоки GPU размером в степень двойки; real-time-задачи ограничены по тому, сколько GPU они могут «переключить» между соседними тактами; начатую задачу нельзя прервать. Целевая функция начисляет награду за размещение блочной задачи (приоритет, умноженный на затухающий во времени вес) и штрафует за недообслуженный спрос в реальном времени; штраф за спрос выставлен в 5, 10 раз выше награды за блочное размещение, так задержки для real-time жёстко приоритизированы внутри той же оптимизации, а не отдельным автоскейлером. Поверх формальной модели работает быстрая эвристика, которая по конструкции всегда выдаёт легальное размещение: решение укладывается в 1, 2 мс на пяти состязательных сценариях и в 15 мс на сценарии 64 GPU / 30 задач, достаточно быстро, чтобы пересчитывать план на каждый входящий запрос. Есть и «полный» режим, который берёт решение быстрой эвристики как стартовую точку и пытается улучшить его формальной моделью, для периодического пересмотра, а не для расчёта по каждому запросу.
Ключевые факты
- На семи тестовых сценариях (одинаковое железо и нагрузка) аллокатор поднял загрузку GPU до 33 процентных пунктов и взвешенную по приоритету полезную работу, до 105% по сравнению с FIFO.
- Сильнейший случай, сценарий с упором на обучение на 8 GPU: загрузка выросла с 53,6% до 87,0%, ценность выросла более чем вдвое (+105%).
- В тесте на масштаб (30 задач, 64 GPU) загрузка и число завершённых задач у FIFO и аллокатора совпали (44,9%, 27 из 30), но аллокатор дал на 15,9% больше ценности, загрузка сама по себе не отражает результат.
- При одинаковом приоритете у всех задач аллокатор всё равно поднял загрузку с 76,8% до 87,5% и ценность на 23,1%, часть выигрыша даёт само планирование на весь горизонт вперёд, а не только приоритезация.
- Решение считается за 1, 2 мс на пяти состязательных сценариях и за 15 мс на сценарии 64 GPU/30 задач, достаточно быстро для пересчёта на каждый входящий запрос.
Почему это важно
GPU, дорогой и дефицитный ресурс, и статья показывает, что заметную часть его простоя создаёт не нехватка железа, а сам алгоритм распределения. FIFO-планировщик вынужден резервировать GPU под пиковый спрос real-time-инференса на весь день и раздаёт остальное строго в порядке поступления заявок, без учёта приоритета, из-за этого простаивает то, что формально «занято» резервом. Замена только порядка принятия решений, без единого нового чипа, подняла загрузку на десятки процентных пунктов в нескольких сценариях.
Кому это важно
В первую очередь, командам, которые управляют смешанным GPU-кластером: одновременно держат real-time-инференс с меняющимся трафиком и «блочные» задачи вроде обучения, батч-инференса и квантования. Именно на стыке этих двух типов нагрузки, по описанию статьи, и теряется больше всего мощности при простом FIFO-подходе. Материал также адресован MLOps- и инфраструктурным инженерам, которые проектируют или выбирают планировщик для GPU-кластера.
Как это применить
В статье описана логика, а не готовый продукт: пять ограничений легального размещения (одна задача на GPU за такт, непрерывные блоки для «блочных» задач, лимит на переключение GPU у real-time-задач между тактами, запрет прерывать начатую работу) и целевая функция, где штраф за недообслуженный real-time-спрос в 5, 10 раз выше награды за блочное размещение. Быстрая эвристика по конструкции выдаёт только легальные размещения и укладывается в 1, 2 мс (15 мс на 64 GPU/30 задачах), то есть рассчитана на пересчёт на каждый входящий запрос, а не на периодический батч-пересчёт. В тексте нет ссылки на код, статью или готовый сервис, применить подход можно только повторив его логику у себя.
Можно ли доверять
Материал опубликован в блоге аккаунта Dharma AI на платформе Hugging Face, это не официальная публикация самой компании Hugging Face, а командный пост (Team Article) аккаунта Dharma-AI, с перечисленными на странице поста участниками (Gabriel Pimenta de Freitas Cardoso, Breno de Almeida Beleza, Francisco de Almeida Rocha Alves, Bruno Duarte и ещё трое), в метаданных item эти имена не отражены; ссылок на код, статью или датасет нет, модель используемых GPU (например, A100 или H100) не названа, как и реальный кластер или источник данных о трафике для бенчмарков. Из пяти состязательных сценариев по числам расписаны только два (смешанный контрольный и с упором на обучение), остальные три упомянуты без разбивки. Сравнение идёт только с FIFO, без сопоставления с популярными планировщиками вроде Kubernetes или Slurm. Это самоотчёт разработчиков без независимой проверки.
Риски и подводные камни
Сами авторы оговаривают: весь расчёт опирается на прогноз того, сколько GPU-часов потребует задача и сколько будет real-time-трафика, а это предсказания, а не заданные величины, и качество планировщика ограничено их точностью. Единого универсального предсказателя, по их словам, недостаточно, потому что у четырёх типов нагрузки разная природа затрат, а какого решения эта задача прогнозирования требует, статья не раскрывает. Отдельно стоит учитывать, что самый эффектный результат, рост со 53,6% до 87,0% загрузки и +105% ценности, получен относительно одного конкретного порядка поступления заявок в FIFO, а не усреднён по разным порядкам, и данных о работе на реальном продакшен-кластере или о масштабе выше 64 GPU / 30 задач в тексте нет.
««Держать GPU занятыми», это не решение, которое способна исполнить система. Настоящее решение куда уже и труднее: какой GPU выполняет какую задачу, на каком такте и с каким приоритетом.»
— блог Dharma AI на Hugging Face