Инфраструктура, управляемая стоимостью

Почему аренда GPU часто оказывается избыточной и как спроектировать модель оплаты в Infracost

Введение

Типичная задача выглядит так — команда ML-платформы получает бюджет и, чтобы не зависеть от доступности мощностей, арендует GPU-кластер на год. Решение кажется разумным: цена за час ниже, чем у on-demand, очередей нет, инженеры спокойны, стоимость спрогнозирована и включена в бюджет. Через полгода кто-то из аудита видит, что кластер занят примерно треть времени, остальное время узлы стоят включёнными, ничего не обучают и при этом ровно так же стоят денег. Счёт приходит за все часы месяца, а полезная работа выполнена лишь в части из них.

Важно, что никто в этой истории не ошибся в техническом смысле. Кластер настроен корректно, задания запускаются, модели обучаются. Ошибка архитектурная: стоимость инфраструктуры считалась как фиксированная строка бюджета, а не как функция реального профиля нагрузки. Мы привыкли проектировать надёжность через SLA, резервирование и отказоустойчивость, безопасность через модель угроз и контроль доступа. Стоимость же слишком часто остаётся побочным эффектом, который обнаруживается постфактум.

Я предлагаю относиться к стоимости как к проектируемому свойству системы. Тезис простой: нагрузка на GPU при обучении моделей принципиально неравномерна, поэтому постоянная аренда мощностей с длинными обязательствами в большинстве случаев неоправданно дорога. Разумнее планировать не далее чем на месяц вперёд, выделять минимально необходимую базу под обязательство, а пики докупать по запросу. Решение при этом принимается не интуитивно, а по расчёту, причём расчёт делается на инфраструктуре, описанной как код. Инфраструктура управляется через контролируемые изменения и мы всегда имеем базу для расчёта стоимости и контроля изменений стоимости в ретроспективе. Одним из самых популярных инструментов такого контроля выступает Infracost.

Такой подход я называю инфраструктурой, управляемой стоимостью (cost-driven infrastructure) и процесс пересмотра стоимости и её прогноза должен стать таким же регулярным процессом проекта как оценка техдолга или контроля дрейфа показателей.

Почему GPU простаивают

Разработка модели не похожа на работу веб-сервиса, у которого есть более-менее сглаженный поток запросов. Это цикл «данные — эксперимент — оценка — отладка», и в каждой фазе потребность в вычислительных мощностях разная. Подготовка и очистка данных идёт в основном на CPU и требует в первую очередь объемов хранилища. Запуск эксперимента требует GPU, но только на время самого прогона. Затем наступает оценка результатов, разбор ошибок, правка кода, и всё это время дорогие ускорители ничего не делают. Перед релизом потребность резко вырастает: нужно запустить сразу несколько вариантов, перепроверить метрики, повторить обучение с исправленными данными. После релиза снова наступает затишье.

Эта картина подтверждается не только практикой, но и публичными исследованиями. Команда Shanghai AI Lab проанализировала трассы кластеров Acme, в которых работают 4 704 GPU A100, и описала их в работе, опубликованной на NSDI 2024 [1]. Медианная утилизация GPU в задачах разработки LLM там оказалась очень высокой, около 99%, но распределение нагрузки бимодально: ускорители либо почти полностью заняты, либо почти простаивают, как это бывает при оценке моделей и отладке. Там же отмечено, что сетевые адаптеры простаивают более 60% времени. Иначе говоря, «средняя загрузка» плохо описывает такую систему, потому что у неё нет типичного состояния. Есть два крайних режима, и между ними система переключается.

Второе наблюдение касается размера заданий. Авторы работы SAKURAONE, описавшие динамику нагрузки в однотенантной среде разработки LLM, показывают, что крупные задания загружают GPU хорошо, а мелкие, на один-два узла, имеют медианную утилизацию всего 17–23% [2]. Они же приводят цифру, которая заставляет задуматься: отменённые задания составляют 73,5% всего занятого GPU-времени. Это не значит, что отмена всегда ошибка. Для исследователя быстро остановить неудачный эксперимент как раз правильно. Но платит за это инфраструктура, и платит по тарифу, рассчитанному на полезную работу.

Третий пример показывает, что даже занятый GPU не всегда занят полезным делом. По публикации Backblaze на данных Adobe, при первом профилировании около двух третей GPU-времени уходило на ожидание данных [3]. После оптимизации входного пайплайна утилизация поднялась примерно до 80%, что близко к практическому потолку. Это отдельная тема, которая решается инженерно, внутри пайплайна, а не закупкой мощностей, но она напоминает, что утилизацию нужно измерять до того, как принимать решение о покупке мощностей.

Из этого следует важное практическое различие между двумя режимами. Большие pretraining-прогоны занимают много узлов подолгу и без пауз, их утилизация высока, и для них длинные обязательства могут быть оправданы. Мелкие экспериментальные задания, напротив, короткие, нерегулярные и часто отменяются, их утилизация низка. Платить за эти два режима одинаково нельзя. Если мы покупаем под экспериментальную нагрузку круглосуточные мощности, мы платим тариф «для непрерывной работы» за работу, которая непрерывной не бывает.

Три способа платить за GPU

Чтобы рассуждать о смешанной модели, нужно ясно представлять, какие способы оплаты у нас есть. Я буду опираться на AWS как на самый документированный случай, но у других провайдеров устроено похоже, только названия отличаются.

On-demand. Почасовая оплата без обязательств. Это самый дорогой тариф за час, зато самый гибкий: узел запускается, когда нужен, и перестаёт стоить денег после остановки. Главное ограничение не в цене, а в доступности. Гарантии, что нужное количество топовых GPU найдётся в нужный момент в нужном регионе, обычный on-demand не даёт.

Краткосрочное резервирование. В AWS это Capacity Blocks for ML. Блок можно забронировать на срок от одного до 14 дней или на срок, кратный семи дням, вплоть до 182 дней, причём бронировать можно за срок до восьми недель вперёд [4]. Оплата вносится при бронировании, отменить блок нельзя, в одном блоке доступно до 64 инстансов. Поддерживаются семейства P4d, P4de, P5, P5e, P5en и P6. Цена зависит от спроса, публикуется за accelerator-hour и обычно лежит между on-demand и годовым резервированием [5]. Главное достоинство блока в том, что он даёт гарантию доступности на конкретное окно, то есть решает именно ту проблему, которую on-demand не решает. У многих других провайдеров есть аналог в виде помесячных committed-планов.

Долгосрочные обязательства. Reserved Instances и Savings Plans на один или три года. Провайдер даёт скидку в обмен на то, что вы платите за мощность независимо от того, используете её или нет. Для p4d.24xlarge в us-east-1 при годовом резервировании без предоплаты ориентир по ценовым агрегаторам составляет около 13,92 $ в час, то есть порядка 37% скидки к on-demand [6].

!!! note «

Цены резервирования в этой статье взяты из агрегаторов и относятся к 2026 году. Это ориентир для иллюстрации метода, а не данные для бюджета. Перед планированием закупки сверьте цифры с актуальным официальным прайс-листом провайдера и проверьте условия конкретного плана.

Сведём три способа в одну таблицу.

Показатель

On-demand

Краткосрочное резервирование

Долгосрочное обязательство (1–3 года)

Цена за час

Максимальная

Между on-demand и годовым резервом

Минимальная

Гибкость

Полная

Ограничена окном бронирования

Низкая

Гарантия доступности

Нет

Есть на период блока

Зависит от типа резервирования

Горизонт планирования

Не нужен

Дни и недели, до 8 недель вперёд

Годы

Риск недоиспользования

Нет

Платите за весь блок, отмена невозможна

Платите за всё время вне зависимости от загрузки

Из таблицы видно, что дёшево и гибко одновременно не бывает, и это две стороны одной и той же медали. Поэтому вопрос формулируется не «какой тариф выбрать», а «какую часть нагрузки на какой тариф отнести». Ответить на него можно только расчётом, и для расчёта нужен удобный инструмент.

Стоимость как код: Infracost

Если инфраструктура описана в Terraform, то её стоимость можно посчитать до применения. Именно эту задачу решает Infracost [7]. Он читает код конфигурации, находит ресурсы, запрашивает цены у провайдера и выдаёт помесячную оценку с разбивкой по ресурсам. Это превращает вопрос «сколько это будет стоить» из предположения в проверяемое число, которое можно получить на этапе ревью, а не в конце месяца.

Вот минимальный пример: один узел с восемью GPU A100.

resource "aws_instance" "train_node" { ami = var.dlami_id instance_type = "p4d.24xlarge" tags = { team = "nlp-research" project = "ranker-v3" env = "training" }}

Для такой конфигурации Infracost возвращает оценку on-demand: 21,96 $ в час, то есть 16 029 $ в месяц при 730 часах. Хранилище, сеть и прочие ресурсы считаются отдельными строками. Для ориентира приведу цены нескольких GPU-инстансов, полученные тем же способом (AWS, us-east-1, Linux, 730 часов в месяце).

Инстанс

GPU

$/час

$/месяц

p5.48xlarge

8× H100

55,04

40 179

p4d.24xlarge

8× A100 40 GB

21,96

16 029

g5.12xlarge

4× A10G

5,67

4 141

g6.12xlarge

4× L4

4,60

3 359

g5.xlarge

1× A10G

1,01

734

Запуск в CI сводится к одной команде.

infracost scan

Практическая ценность не в самой цифре, а в том, где она появляется. Если запускать сканирование в CI, то в каждом pull request будет видна дельта стоимости: изменение, добавляющее ещё два узла p4d, покажет рост счёта прямо в обсуждении кода, пока его ещё можно отклонить. Поверх этого Infracost поддерживает бюджеты и политики, которые могут остановить изменение, если оно выходит за допустимые рамки. А теги позволяют разносить затраты по командам и проектам, что понадобится нам в конце месяца для сравнения плана и факта.

Текущая версия Infracost считает on-demand тарифы. Цены резервирования и Capacity Blocks берутся из прайс-листов провайдера, а не из оценки инструмента. В старых версиях резервирование можно было задавать через usage-файл [8], но полагаться на это для смешанной схемы я бы не стал. Поэтому расчёт «база плюс пики» делается поверх оценки Infracost: часовая on-demand цена берётся из инструмента, цена обязательства из прайса провайдера, а сама арифметика выполняется в простой таблице или небольшом скрипте. Это не недостаток подхода, а разделение ответственности: Infracost отвечает за то, что он знает хорошо, то есть за описание ресурсов и актуальные тарифы, а решение о структуре обязательств остаётся за человеком.

Модель «база плюс пики»

Ядро этого метода умещается в одну формулу. Для каждого узла нужно выяснить, выгоднее ли держать его по обязательству или брать по запросу. Обязательство стоит фиксированно за весь месяц, on-demand стоит пропорционально часам использования. Значит, существует порог загрузки, ниже которого обязательство проигрывает. Назовём его точкой безубыточности утилизации:

u* = цена_обязательства / цена_on-demand

Здесь обе цены берутся за час. Если узел нужен больше чем u* времени в месяце, его выгоднее взять по обязательству. Если меньше, выгоднее брать по запросу и платить только за реально использованные часы. Для p4d.24xlarge получаем 13,92 / 21,96 ≈ 63%. Порог определяется ценами, а не размерами нашей команды: чем больше скидка за обязательство, тем ниже u*, и тем раньше резервирование начинает окупаться. При скидке 37% нужно загружать узел почти две трети времени, чтобы не переплатить.

Рассмотрим сквозной пример. Допустим, команде нужен один узел p4d.24xlarge постоянно: регулярное дообучение и сервинг экспериментальных моделей занимают 730 часов в месяц. Второй узел нужен примерно 200 часов в месяц под крупные еженедельные прогоны. Ещё два узла нужны по 100 часов в месяц каждый под пиковые эксперименты перед релизом. Фактическая потребность составляет 730 + 200 + 100 + 100 = 1 130 узло-часов в месяц, пиковая одновременная потребность равна четырём узлам. Рассмотрим четыре способа это сделать.

Сценарий

Состав

Стоимость в месяц

A. «Арендуем с запасом»

4 узла on-demand 24/7: 4 × 16 029

64 116 $

B. «Резервируем всё»

4 узла по годовому обязательству: 4 × 10 162

40 648 $

C. «Всё по запросу, только когда нужно»

1 130 ч × 21,96

24 812 $

D. «База плюс пики»

1 узел по обязательству (10 162 $) + 400 часов on-demand (400 × 21,96 = 8 783 $)

18 945 $

Часовая ставка в таблицах округлена до цента, суммы посчитаны по точной ставке Infracost. Сценарий A самый простой организационно и самый дорогой. Сценарий B снижает цену часа, но утилизация там составляет 1 130 / 2 920 = 39%, что заметно ниже порога u*: мы платим за три узла, которые большую часть месяца стоят без дела. Сценарий C выглядит выгодным, но требует жёсткой дисциплины выключения и несёт риск, что в момент пика нужных узлов в on-demand не окажется.

Сценарий D даёт оценку стоимости всего 18 945 $ и оказывается дешевле B на 53% и дешевле A на 70%. Но самое интересное сравнение с C: смешанная схема дешевле даже «идеального» on-demand примерно на 5 900 $ в месяц. Причина в том, что базовый узел загружен на 100% и с запасом проходит порог u* ≈ 63%, поэтому для него обязательство выгоднее почасовой оплаты. Второй узел загружен на 200 / 730 ≈ 27%, это ниже порога, и резервировать его невыгодно. Значит, правильное решение здесь такое: один узел в базу, остальные по запросу. Это не общее правило «резервируй треть», а результат расчёта на конкретном профиле нагрузки и конкретных ценах. Если цены изменятся или профиль сдвинется, ответ может стать другим, и именно поэтому расчёт стоит повторять регулярно.

Ежемесячное планирование

Модель работает только тогда, когда её исходные данные обновляются. Поэтому я рекомендую использовать ежемесячный цикл, в котором участвуют три роли: архитектор, который отвечает за структуру решения и расчёт, FinOps или финансовый директор, который отвечает за бюджет и условия обязательств, и лиды ML-команд, которые знают свои планы на нагрузку оборудования. Принципы FinOps, то есть совместная ответственность инженерии, финансов и бизнеса за облачные расходы, хорошо описаны в FinOps Framework [9], и этот подход по сути является его применением к GPU-нагрузке.

Цикл состоит из пяти шагов.

Первый: каждая команда присылает календарь обучений на месяц, то есть какие прогоны планируются, сколько узлов нужно и на сколько часов. Не нужна точность до часа, достаточно честной оценки и признания, что часть запусков может не состояться.

Второй: архитектор готовит два-три варианта Terraform, например «только база» и «база плюс пики», и прогоняет их через Infracost для оценки стоимости.

Третий: по результатам расчёта принимается решение об обязательствах, то есть сколько узлов вынести в базу и менять ли существующие обязательства.

Четвёртый: пики бронируются заранее. Если крупные прогоны известны за недели, имеет смысл заказать Capacity Blocks или запросить квоты, не дожидаясь момента, когда нужные узлы понадобятся срочно.

Пятый: в конце месяца план сравнивается с фактом по тегам, и расхождения становятся входными данными для следующего цикла.

Чтобы «пики по запросу» не превращались в ручную работу, нужен механизм, который делает этот режим автоматическим. На практике это очередь заданий с автоскейлингом: Kubernetes с Karpenter, который поднимает узлы под поставленные в очередь поды и гасит их, когда работа закончена, или Slurm с эластичным пулом. Тогда инженеру не нужно помнить о выключении, а базовая конфигурация просто всегда используется первой, и только избыток спускается на конфигурацию по запросу. Без такой автоматизации сценарий C, который мы разбирали выше, остаётся теоретическим: стоимость экономится только в том случае, если лишние узлы действительно гаснут.

Роли здесь важнее, чем инструменты. Если архитектор считает, но не имеет полномочий влиять на закупки, расчёт остаётся справкой. Если FinOps покупает обязательства без профиля нагрузки, получается сценарий B. Если лиды команд не присылают планы, база определяется по прошлому месяцу, и мы всегда на шаг позади. Регулярный цикл нужен именно для того, чтобы эти три стороны регулярно синхронизировали свои планы и решения.

Ограничения и риски

У подхода есть границы, и о них стоит помнить.

Первое: доступность GPU on-demand не гарантирована, особенно для топовых ускорителей. Сценарий, в котором пики полностью зависят от того, найдутся ли свободные узлы в момент запроса, несёт реальный риск срыва сроков. Поэтому важные пики лучше закрывать краткосрочными резервированиями, а on-demand оставлять для менее критичной части нагрузки.

Второе: цены меняются. В 2026 году AWS повышал цены Capacity Blocks: в январе примерно на 15%, а затем ещё несколько раз в течение года [5]. Значит, порог u* не константа, и расчёт, сделанный полгода назад, может давать неверный ответ. Цифры в этой статье тоже стоит рассматривать как иллюстрацию на конкретный момент времени и обязательно перепроверять перед запуском проекта.

Третье: GPU не единственная статья расходов. Хранилище датасетов и чекпойнтов, сетевой трафик, egress при переносе данных между регионами или наружу тоже стоят денег, и в отдельных проектах они сопоставимы с вычислениями. Оптимизация одной статьи при игнорировании остальных даёт обманчивую экономию, поэтому в расчёт нужно включать всю инфраструктуру, а не только GPU.

Четвёртое: длинные непрерывные pretraining-прогоны остаются случаем, где годовое обязательство действительно выигрывает. Если кластер занят одной большой задачей неделями без пауз, его утилизация близка к 100%, она заведомо выше u*, и скидка за обязательство работает в полную силу. Смешанная модель не отрицает долгосрочных обязательств, она лишь требует, чтобы они применялись к той части нагрузки, которая этого заслуживает.

Пятое, и, пожалуй, самое важное: организационный риск. Если никто не владеет этим решением, то есть нет человека, который раз в месяц пересчитывает базу, всё довольно быстро возвращается к привычному «арендуем с запасом». Это самый безопасный выбор для каждого отдельного участника и самый дорогой для компании в целом. Чтобы этого не происходило, у решения должен быть владелец с понятной ответственностью и регулярный цикл актуализации.

Заключение

Мы начали с кластера, который арендован на год и загружен на треть. Его проблема не в железе и не в провайдере, а в том, что нагрузка и стоимость не была спроектирована. GPU-нагрузка при разработке моделей бимодальна, мелкие задания утилизируют ускорители плохо, и платить за такую нагрузку тарифом «для непрерывной работы» обычно означает переплачивать.

Альтернатива состоит в смешанной модели. Минимальная база, которая загружена выше порога u*, закрывается обязательством, а всё остальное берётся по запросу или краткосрочными резервированиями, забронированными заранее. На примере из четырёх узлов такая схема обошлась в 18 945 $ в месяц против 64 116 $ при аренде с запасом. Этот результат не универсален, но представленный метод позволяет сравнивать утилизацию узла с порогом и принимать решение по расчёту, а не по ощущению.

Infracost делает этот подход практичным, потому что приносит стоимость в процесс разработки инфраструктуры. Когда оценка видна в pull request, а бюджеты и политики защищают от случайных решений, стоимость становится таким же проверяемым свойством системы, как надёжность или безопасность. Она видна до того, как превращается в счёт, и в этом основная идея инфраструктуры, управляемой стоимостью.

Источники

1. Hu, Q. et al. Characterization of Large Language Model Development in the Datacenter. NSDI 2024. [https://arxiv.org/abs/2403.07648]

2. SAKURAONE: An Open Ethernet-Based AI HPC System and Its Observed Workload Dynamics in a Single-Tenant LLM Development Environment. arXiv:2604.13600, 2026. [https://arxiv.org/abs/2604.13600]

3. Gigazine. Why are GPUs unnecessarily idle during AI training, and what measures has Adobe taken to address this? (по материалам Backblaze), 2026. [https://gigazine.net/gsc_news/en/20260826-gpu-idle/]

4. AWS. Amazon EC2 Capacity Blocks for ML — User Guide. [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-capacity-blocks.html]

5. AWS. Capacity Blocks pricing. [https://aws.amazon.com/ec2/capacityblocks/pricing/]

6. Vantage. EC2 instance pricing comparison (p4d.24xlarge). [https://instances.vantage.sh/aws/ec2/p4d.24xlarge]

7. Infracost. Documentation. [https://www.infracost.io/docs/]

8. Infracost. Usage-based resources (EC2 reserved instance usage parameters). [https://www.infracost.io/docs/features/usage_based_resources/]

9. FinOps Foundation. FinOps Framework. [https://www.finops.org/framework/]

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев