Создание планировщика кластера для приоритизации высокоэффективных исследований при сохранении полной загрузки
Команда AI Infrastructure в Ai2 отвечает за предоставление вычислительных мощностей GPU для института, ориентируясь в первую очередь на крупные распределенные рабочие нагрузки. Мы рассматриваем эту задачу как пирамиду из четырех метрик, которые дополняют друг друга.
Фундаментом является доступность: как часто оборудование исправно и готово к работе. Выше находится загрузка: доля доступного времени, выделенная под конкретную рабочую нагрузку. Далее идет эффективность: как часто для получения ресурсов выбираются наиболее ценные задачи. Вершиной пирамиды является утилизация: доля мощности GPU, используемая в течение всего времени выполнения задачи.
Эта статья посвящена повышению эффективности наших решений по планированию. Недавно мы заменили планировщик на основе приоритетов системой, включающей бюджеты времени GPU, иерархическое справедливое распределение и контракт с разделением времени. В результате мы перевели дискуссию о том, сколько времени GPU заслуживает каждый исследовательский проект, из операционной задачи, решаемой в индивидуальном порядке, в прозрачный процесс административного бюджетирования.
Переподписка (Overcommitting)
В Ai2 мы управляем тысячами GPU NVIDIA H100, B200 и B300, организованными в кластеры размером от 88 до 1024 GPU. Эти кластеры созданы для крупномасштабного распределенного обучения моделей ИИ и обслуживают группу из примерно 150 внутренних исследователей, чья работа охватывает широкий спектр областей ИИ, включая полный цикл обучения LLM и VLM, симуляцию обучения с подкреплением (RL) в робототехнике и пост-обучение для научных агентных сценариев.
Как и во многих лабораториях, спрос на время GPU у нас значительно превышает предложение. Исходя из поданных заявок, в любой момент времени у нас есть невыполненные запросы на 2-3 раза больше GPU, чем доступно. Один из способов взглянуть на это — представить, что на каждый доступный час работы GPU в нашем кластере претендуют 2-3 различные исследовательские задачи.
Исторически мы использовали планировщик на основе приоритетов и позволяли рабочим нагрузкам отказываться от возможности прерывания. У каждой команды был лимит на количество одновременных GPU, которые могли использоваться задачами, защищенными от прерывания. Прерываемые задачи могли превышать этот лимит на простаивающих GPU. Эта стратегия приводила к предсказуемым патологиям. Например, мы наблюдали случаи «сквоттинга» GPU, когда пользователи запускали фиктивные задачи, к которым могли подключиться при необходимости. Это происходило потому, что исследователи обнаружили, что не могут запускать отладочные задачи с достаточно низкой задержкой для решения проблем в реальном времени. Мы также наблюдали инфляцию приоритетов, когда в конечном итоге 100% запланированных задач имели ВЫСОКИЙ приоритет. Это означало, что задачи с более низким приоритетом вообще оставались без времени GPU. Поскольку возможность прерывания была опциональной, мы также обнаружили, что наши дежурные инженеры тратили большую часть времени на обработку тикетов, договариваясь об организованном завершении непрерываемых задач, запущенных на хостах с известными проблемами обслуживания.
Трагедия общин
Когда эти проблемы проявились, мы медленно выявляли их первопричины. Наши первоначальные попытки обеспечить получение времени GPU для наиболее важной работы были сосредоточены на более жестком контроле установки приоритетов и, в конечном итоге, на обходе планировщика на основе приоритетов путем явного закрепления монополий на GPU за важными проектами. Хотя поначалу мы этого не осознавали, мы создали идеальную лабораторию для наблюдения «трагедии общин». Люди конкурировали за дефицитный общий ресурс и, стремясь максимизировать индивидуальные результаты, достигали неоптимального глобального результата и злоупотребляли базовым ресурсом.
Мы были далеко не первыми, кто заметил подобное взаимодействие. Распределение ресурсов — это увлекательная область исследований, сочетающая разработку алгоритмов, экономику и управление системами. Центральная проблема заключается в том, что пользователи часто знают ценность своих задач лучше, чем организация, но у них могут быть стимулы скрывать эту ценность или удерживать ресурсы, даже когда это вредит общей производительности. Например, в своей статье 2011 года, представляющей Dominant Resource Fairness, Годси и соавторы рассказывают анекдот о том, как поисковая компания предоставляла выделенные машины для задач только в том случае, если пользователи могли гарантировать высокую утилизацию. Вскоре они обнаружили, что «пользователи вставляли в свой код бесконечные циклы, чтобы искусственно завышать уровни утилизации». Оборудование меняется, но фундаментальные проблемы, делающие распределение ресурсов сложным, остаются.
Бюджеты, а не расписания
Классическое решение трагедии общин — приватизация общего ресурса: владельцы получают стимул максимизировать ценность своей собственности. Когда мы назначали командам монополии на наборы GPU, мы уже делали нечто подобное, но это было слишком грубо. Это приводило к простою GPU из-за сезонности исследований. Команды готовы проводить эксперименты и обучение в разное время, поэтому назначение монополии гарантировало, что будут периоды, когда ни одна задача не готова к выполнению, в то время как другая команда будет ждать мощностей.
Мы вручную решали задачу о рюкзаке, пытаясь вписать динамически меняющиеся исследовательские потребности в статичное расписание. Мы хотели получить стимул владения, но также хотели сохранить полную загрузку GPU.
Мы решили итерировать модель владения. Вместо выдачи командам GPU мы решили распределять часть времени GPU. Прогнозирование спроса в будущем потребовало бы знания результатов новых научных экспериментов, поэтому его невозможно предсказать с точностью. Однако приоритетность исследовательских усилий — это вопрос стратегии, и его легче обсуждать и решать заранее. Вместо того чтобы пытаться решить головоломку планирования, мы позволили руководству мыслить как инвесторам. Прежде чем рабочие нагрузки появятся, решите, как финансировать каждое исследовательское усилие временем GPU, основываясь на их суждении о его вероятном влиянии. Планировщик затем может использовать эту информацию при приоритизации поступающих задач.
Учитывая это, мы разработали иерархическую систему, в которой менеджеры могли пропорционально распределять время GPU между проектами и исследователями, за которых они отвечают. Как показано на диаграмме ниже, это переводит стратегию программы непосредственно в гарантированную долю времени GPU. Проект A1 знает, что имеет 35% долю от общей мощности, независимо от того, сколько других проектов стоят в очереди в других местах.
Значения в скобках представляют общую мощность кластера, назначенную конечному проекту.
В этой системе каждый запрос на время GPU должен быть обеспечен бюджетом, иначе он не защищен от вытеснения. В старой системе высокий приоритет (HIGH) не требовал затрат, а невозможность вытеснения позволяла команде бесконечно занимать лимит параллельно используемых GPU, поэтому ими пользовались все. Теперь ничто не дается бесплатно, поэтому любая хитрость для получения времени GPU расходует квоту пользователя, получающего выгоду. «Захват» ресурсов — это пустая трата бюджета команды. Наша стратегия заключается в том, чтобы сделать попытки обмануть планировщик более затратными, чем честное участие в обсуждении увеличения бюджета. Мы постоянно совершенствуем этот процесс пересмотра бюджета, но ключевыми требованиями являются частые возможности для исследователей обосновать необходимое им время, а также принятие решений менеджерами, которые лучше всего понимают контекст соответствующих компромиссов. Это означает, что решения о распределении в рамках исследовательского проекта принимает ведущий исследователь, в рамках исследовательской программы — главный исследователь, а между программами — ведущий менеджер программы или генеральный директор.
Справедливое распределение (Fair-share)
В дополнение к этому инструменту бюджетирования времени GPU мы создали иерархический планировщик справедливого распределения для управления фактической занятостью квот по всему дереву программы. Алгоритм здесь не нов — иерархическое справедливое распределение за временное окно является частью линии, восходящей к Hadoop Fair Scheduler in 2009, и тот же подход активно используется сегодня в Fair Tree в SLURM и Fair Scheduler в YARN. Новым для нас являются входные данные: дерево отражает структуру исследовательской программы, а веса — это бюджеты, установленные менеджерами, а не статические квоты.
Планировщик отслеживает занятость за скользящее окно ретроспективного анализа (по умолчанию мы используем 7 дней) и сортирует рабочие нагрузки из недоиспользуемых квот выше тех, что из переиспользуемых. Таким образом, в течение недельного диапазона мы можем ожидать, что каждая группа получит свое выделенное время GPU, если они активно отправляют рабочие нагрузки с достаточным спросом.
«Новый планировщик создает ощущение, что у нас появилось дополнительные 30% вычислительных мощностей. В старом планировщике, если у нас были моменты, когда мы не использовали весь лимит слотов, эти вычисления по сути пропадали. Теперь с новым планировщиком, если это происходит, мы можем позже превысить наш лимит квоты и при этом видеть, что наши задания планируются быстро и без вытеснения, по сути позволяя нам вернуть эти вычисления. Наши рабочие нагрузки часто носят импульсный характер, поэтому это вернуло нам значительный объем вычислительных мощностей». — Крис Кларк
Планировщик различает два вида занятости. Распределенная занятость — это время, в течение которого рабочая нагрузка оплачивается из бюджета. Это расходует квоты владельца рабочей нагрузки, что влияет на расчет бюджета справедливого распределения, и такие рабочие нагрузки защищены от вытеснения в течение минимального окна выполнения. Нераспределенная занятость не оплачивается из какого-либо бюджета, с самого начала не защищена и может быть вытеснена любым распределенным запросом. Это позволяет нам поддерживать полную загрузку GPU, даже когда квоты не совсем соответствуют спросу, и не дает командам отказываться от свободных циклов GPU.
Соглашение о планировании
Дополнительной особенностью распределенного обучения, которая затрудняет справедливое распределение ресурсов, является то, что рабочие нагрузки могут выполняться очень долго. Задания на обучение регулярно выполняются часами, днями, а иногда даже неделями. После планирования рабочая нагрузка может оставаться на назначенных ей GPU неделю или дольше, не давая другим возможности получить свое бюджетное время. Это свойство системы, которое сделало возможным «захват» GPU. Именно оно заставляло инженеров дежурной смены договариваться с владельцами долго выполняющихся заданий для решения текущих проблем с обслуживанием.
Чтобы решить эти проблемы, мы ввели «соглашение о планировании». В обмен на доступ к кластеру рабочая нагрузка должна объявить свое минимальное время выполнения или кратчайший объем занятости, необходимый для достижения значимого прогресса. В течение этого времени рабочая нагрузка защищена от вытеснения. Это дает исследователю гарантию прогресса, а планировщику — право на перебалансировку после того, как этот прогресс достигнут, автоматически возвращая в очередь возобновляемые рабочие нагрузки. Альтернативно, пользователь может установить минимальное время выполнения на ноль, что означает, что время GPU должно быть нераспределенным. Такие рабочие нагрузки всегда подвержены вытеснению, но они также бесплатны в том смысле, что не списываются из бюджета.
Жизненный цикл рабочей нагрузки следует этой схеме:
- Рабочая нагрузка отправляется с минимальным временем выполнения и указанием, является ли она возобновляемой.
- Рабочая нагрузка планируется в соответствии с алгоритмом справедливого распределения, взвешенным по соотношению фактической занятости к выделенному времени в окне ретроспективного анализа.
- Рабочая нагрузка выполняется в течение минимального времени выполнения, которое списывается с ее квот.
- Рабочая нагрузка может продолжать выполняться до тех пор, пока связанные с ней квоты продолжают отдавать ей приоритет перед другими. Это время также списывается с ее квот.
- Она может быть вытеснена и возвращена в очередь, что возвращает к шагу 2.
- Рабочая нагрузка завершается, освобождая свои права на любые ресурсы.
Вместе эти соглашения добавляют временное разделение (time-slicing) в наш планировщик. Выполняющиеся рабочие нагрузки могут быть удалены и возвращены в очередь автоматически, что позволяет справедливому распределению прийти к равновесию и лишает стимулов к «захвату» ресурсов. Они также позволяют неисправным хостам освобождать свои рабочие нагрузки по достижении ими минимального времени выполнения, поэтому ремонтные работы могут быть полностью автоматизированы. Этот последний пункт оказался важнее, чем мы предполагали при планировании этой работы. Это сократило количество ремонтов, требующих участия человека, на 74%, что стало огромной экономией усилий дежурных инженеров.
Симуляции
Мы знаем, что изменения политики планирования могут иметь непредвиденные последствия. Нулевая сумма проблемы означает, что предоставление времени одному исследователю означает отнятие его у другого. Пользователи, которые проигрывают в этом обмене, склонны искать новые обходные пути. Перед внедрением системы, основанной на бюджете, мы хотели быстро найти способ предсказать, где могут возникнуть более длительные периоды ожидания, и протестировать параметры конфигурации, такие как длина окна ретроспективного анализа или максимальное значение для минимального времени выполнения (мы выбрали 8 часов).
Мы создали небольшую среду симуляции, которая принимает набор рабочих нагрузок и график их отправки в качестве входных данных и позволяет планировщику принимать решения о вытеснении и назначении GPU. Зная запрошенное каждой рабочей нагрузкой количество GPU и общее время выполнения, симулятор мог перескакивать к моментам планирования и предоставлять анализ времени ожидания в очереди, событий вытеснения и распределения времени GPU по проектам за много симулированных дней всего за несколько секунд. Мы запустили симулятор как на исторических данных об отправке заданий, так и на сконструированных сценариях, которые хотели лучше понять.
Одна из гипотез, которую мы хотели проверить, касалась «отладочных рабочих нагрузок». Для таких задач требуется небольшое количество GPU и минимальное время выполнения 15 минут или меньше, чего достаточно, чтобы пользователь мог увидеть, успешно ли запускается задача или она аварийно завершается из-за ошибки или неправильной конфигурации. Мы хотели узнать, будет ли время ожидания в очереди для таких задач меньше, чем для более крупных тренировочных нагрузок, которым часто требуется много GPU и часы работы для достижения значимого прогресса. Интуитивно понятно, что такие небольшие задачи должны перемещаться в начало очереди, поскольку маленькую задачу проще разместить, чем большую. Однако важна была точная задержка в очереди. Короткое ожидание в минуту или две открыло бы новые возможности для разработки, но десятиминутное ожидание стало бы неприемлемым.
Для наших симуляций потребовались вручную созданные тестовые данные, поскольку в наших исторических записях не было достаточного объема таких отладочных нагрузок. Наши результаты подтвердили гипотезу: время ожидания p90 для отладочных нагрузок сократилось с примерно 6 часов до всего 5 минут.
Визуализация симулятора меньшего масштаба для базового планировщика (слева) и нового планировщика «распределений» (справа). Каждая строка — это один GPU; каждый столбец — это задача, окрашенная в соответствии с родительской нагрузкой, по одному оттенку цвета на команду; штриховка обозначает время, когда задачу можно прервать, а красная граница отмечает вытеснение. В базовом варианте длительные срочные задачи никогда не прерываются, а вытеснений в задачах с более низким приоритетом происходит меньше. Новый планировщик обеспечивает большее смешение цветов на каждом GPU, иллюстрируя ротацию занятости между командами.
Результаты
Получив результаты моделирования, в конце июля мы начали поэтапное развертывание по кластерам. Нас интересовало, получили ли выбранные нами рабочие нагрузки отведенное им время, поддерживала ли новая система полную занятость и могли ли исследователи анализировать работу планировщика для принятия обоснованных решений.
С момента развертывания мы наблюдаем, что пользователи и команды стабильно получают выделенное им время GPU. Мы рассчитываем время, причитающееся команде, как ее квоту, ограниченную по часам в соответствии с фактическим спросом. За 30-дневный период тестирования командам было предоставлено 98% причитающихся им часов GPU, при этом 13 из 15 команд получили 95% или более, а худший показатель составил 90%. Занятость кластера оставалась стабильной на уровне 98% как до, так и после изменений, при этом спрос превышал емкость в 2–3 раза в оба периода. 18% предоставленного времени GPU было нераспределенным, что позволило нам поддерживать высокую занятость в периоды, когда финансируемые проекты не были готовы к запуску.
Результаты нашего симулятора оказались верными по направленности, а реальные показатели превзошли наши прогнозы. Время ожидания p90 в очереди для отладочных нагрузок сократилось с 2 часов до 30 секунд при использовании нового планировщика, по сравнению с прогнозом симуляции от 6 часов до 5 минут на основе вручную созданных тестовых сценариев. Стоит отметить, что меньший размер выборки отладочных нагрузок в базовом варианте означал более высокую дисперсию в этих измерениях. Задержка в очереди в целом улучшилась как побочный эффект разделения времени: на нашем крупнейшем кластере H100 медианное время ожидания в очереди сократилось с 5 минут до 24 секунд, а время ожидания p90 сократилось примерно на треть (с 2,8 часов до 1,8 часов).
В сравнении с тремя проблемами, которые мы намеревались решить:
- Сквоттинг: Короткие отладочные нагрузки запускаются менее чем за минуту, что снижает ценность сквоттинга. Стоимость такого поведения списывается с бюджета сквоттера, что не дает им получить время, когда оно им действительно нужно.
Сквоттинг: Короткие отладочные нагрузки запускаются менее чем за минуту, что снижает ценность сквоттинга. Стоимость такого поведения списывается с бюджета сквоттера, что не дает им получить время, когда оно им действительно нужно.
- Инфляция приоритетов: Мы по-прежнему позволяем рабочим нагрузкам объявлять приоритет, но это влияет только на сортировку внутри команды. Менеджеры мотивированы следить за приоритетами в группе, чтобы оптимизировать использование своих бюджетов.
Инфляция приоритетов: Мы по-прежнему позволяем рабочим нагрузкам объявлять приоритет, но это влияет только на сортировку внутри команды. Менеджеры мотивированы следить за приоритетами в группе, чтобы оптимизировать использование своих бюджетов.
- Оперативная работа: Неисправные хосты автоматически освобождаются по мере того, как рабочие нагрузки достигают минимального времени выполнения. Количество ремонтов, требующих участия человека, сократилось на 74%.
Оперативная работа: Неисправные хосты автоматически освобождаются по мере того, как рабочие нагрузки достигают минимального времени выполнения. Количество ремонтов, требующих участия человека, сократилось на 74%.
Проблемы
Кривая обучения оказалась круче, чем мы предполагали. Мы внедряли изменения постепенно, поэтому в первые дни исследователи сталкивались с разным поведением системы в зависимости от того, на какой кластер они направляли задачи. Кроме того, в наших интерфейсах сохранилась старая терминология (например, приоритет рабочей нагрузки), значения которой изменились. Одной документации было недостаточно, чтобы устранить путаницу. Что действительно помогло, так это проведение живых разъяснительных сессий, предоставление форума для исследователей, где они могли задать вопросы, и для инженерной команды, чтобы дать более глубокие описания того, как и почему планировщик принимает решения о приоритезации, используя реальные примеры.
Это был ключевой момент, поскольку он ознаменовал переход от раннего периода разочарования и домыслов к текущему режиму, когда исследовательские группы чаще и шире общаются по поводу потребностей своих экспериментов в GPU. Исследователи теперь участвуют в обсуждении бюджета, четко понимая компромиссы, на которые приходится идти для удовлетворения любого нового запроса.
В дополнение к личным встречам мы представили новые визуализации после запуска, чтобы дать пользователям лучшее представление о том, насколько точно их выделенное время GPU соответствует ожидаемым квотам, и напрямую отобразили метрику, используемую для сортировки очереди рабочих нагрузок. Это дало простое место для проверки, когда задача была вытеснена, чтобы понять причину. Эти визуализации также помогли владельцам бюджетов, которые могли видеть, как время GPU используется в различных проектах под их управлением.
Пример визуализации использования распределения во времени.
Не все сценарии использования стали работать лучше. Помимо распределенного обучения, наши исследователи запускают интерактивные сессии, в ходе которых они выполняют анализ данных и тестируют код обучения непосредственно в процессе его написания. В старой системе исследователь мог поддерживать такую сессию до недели. С появлением разделения времени (time-slicing) на них стало распространяться 8-часовое ограничение на защищенное время выполнения, после чего сессия становится вытесняемой, если она превышает выделенный лимит. Мы не до конца осознавали, насколько исследователи зависят от энергозависимого состояния этих сессий. Вытеснение означало ожидание получения новой сессии, а также ручное восстановление состояния. Опросив исследователей, чтобы понять масштаб проблемы, мы создали два новых проекта в рамках дорожной карты. Мы инвестируем в создание кластера только на базе CPU рядом с нашим локальным хранилищем для сессий разработки, ориентированных на задачи подготовки данных. Это позволит сохранить емкость нашего обучающего кластера для рабочих нагрузок, которые действительно в этом нуждаются. Кроме того, мы планируем создать восстанавливаемые сессии для этих рабочих нагрузок только на базе CPU. Это позволит нам продолжать вытеснять рабочие нагрузки по истечении минимального времени их выполнения для обслуживания или разделения времени, при этом имея возможность восстановить сессию в другом месте без необходимости ее ручного воссоздания исследователем. Мы сможем сохранить эксплуатационные и планировочные преимущества этой новой системы, одновременно улучшая пользовательский опыт.
Мы продолжаем следить за возникающими проблемами. Одна из потенциальных проблем, которую мы исследуем, — это фрагментация емкости, которая может привести к увеличению времени ожидания в очереди для самых крупных рабочих нагрузок. Наша интуиция подсказывает, что защита минимального времени выполнения применяется к тем типам заданий, которые раньше полагались на механизмы вытеснения, чтобы превысить лимит одновременного использования GPU для своей команды. Раньше такие задания могли быть прерваны в любой момент, что потенциально приводило к потере времени, но также упрощало планирование крупных заданий. Теперь у планировщика может быть меньше возможностей прервать множество заданий одновременно, чтобы разместить крупную ожидающую рабочую нагрузку. В настоящее время мы используем наши инструменты симуляции для воспроизведения этой проблемы, одновременно измеряя реальные показатели в производственной среде.
Будущее
Заглядывая за рамки описанной здесь работы по планированию, мы стремимся к вершине пирамиды: утилизации. Нам необходимо обеспечить максимально эффективное выполнение загрузки, создания контрольных точек и самих приложений для обучения, максимизируя ценность запланированного времени, которое получает каждая рабочая нагрузка.
Если вы хотите решать подобные задачи в тесном сотрудничестве с исследователями, присоединяйтесь к нам.









