Сравнить reserved vs spot vs on-demand для ML-инфраструктуры
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Сравнить reserved vs spot vs on-demand для ML-инфраструктуры
1. Цель задачи
Научиться анализировать реальные затраты на облачные вычислительные ресурсы (GPU/CPU) за трёхмесячный период и выбирать оптимальное сочетание моделей покупки (reserved instances, spot instances, on-demand) для ML-ворклоудов. Задача имитирует реальный процесс оптимизации cost-efficiency в production ML-системе. В результате вы получите документ с расчётами и рекомендацией по соотношению типов инстансов, минимизирующему общую стоимость при заданных ограничениях по availability и SLA.
Ключевой результат Таблица с тремя сценариями (консервативный, сбалансированный, агрессивный) и обоснованной рекомендацией, а также Python-скрипт для повторного расчёта при изменении входных данных.
2. Исходные данные
Перед началом необходимо иметь:
| Что нужно | Откуда взять |
|---|---|
| Детальный отчёт о расходе compute-ресурсов за 3 месяца (часы работы, тип инстанса, регион, цена) | AWS Cost and Usage Report (CUR) / Azure Cost Management / GCP Billing export, или симуляция |
| Прайс-лист на on-demand, reserved (1yr/3yr, предоплата), spot для используемых типов инстансов | Официальные страницы провайдера или API ценообразования |
| Характеристики ворклоуда (непрерывные vs пакетные задачи, критичность, допустимое время простоя) | Из проектной документации или опроса команды |
| Метрики использования (средняя загрузка GPU, пики, время суток/weekend) | CloudWatch / Stackdriver / Azure Monitor + Grafana |
Если нет реального датасета — симулируем:
- Сгенерируйте синтетический лог использования за 3 месяца (примерно 500-1000 записей) с помощью Python:
- Типы инстансов: p3.2xlarge (GPU), c5.xlarge (CPU), p4d.24xlarge (GPU) и др.
- Распределение: 60% on-demand, 30% spot, 10% reserved (чтобы была исходная точка)
- Часы работы: по будням с 9 до 18 — пиковая нагрузка, в остальное — batch jobs
- Случайные сбои spot-инстансов (10-20% прерываний)
- Регион: us-east-1 (для простоты)
- Сохраните в CSV с колонками: timestamp, instance_type, region, usage_hours, pricing_model, cost_per_hour
Пример генерации (сохранить как simulate_usage.py):
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
np.random.seed(42)
dates = pd.date_range(start='2025-01-01', end='2025-03-31', freq='H')
instances = ['p3.2xlarge', 'c5.xlarge', 'p4d.24xlarge']
regions = ['us-east-1']
models = ['on_demand', 'spot', 'reserved']
data = []
for t in dates:
for inst in instances:
# 60% on_demand, 30% spot, 10% reserved
model = np.random.choice(models, p=[0.6, 0.3, 0.1])
# пиковые часы (9-18) больше on_demand
if 9 <= t.hour < 18 and model == 'on_demand':
hours = np.random.uniform(0.8, 1.0)
else:
hours = np.random.uniform(0.2, 0.6)
cost = {'p3.2xlarge': 3.06, 'c5.xlarge': 0.34, 'p4d.24xlarge': 32.77}[inst]
data.append([t, inst, regions[0], round(hours,2), model, round(cost*hours,4)])
df = pd.DataFrame(data, columns=['timestamp','instance_type','region','usage_hours','pricing_model','cost'])
df.to_csv('simulated_usage.csv', index=False)
- Скачайте актуальные цены AWS для us-east-1 (или используйте статическую таблицу из приложения).
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Анализ данных | Python 3.11+, pandas, numpy | Обработка логов, статистика, симуляция |
| Визуализация | matplotlib, seaborn | Графики загрузки, распределение cost |
| Облачный провайдер (пример) | AWS | Провайдер для примеров цен |
| API ценообразования | boto3 (AWS Price List API) / опционально | Автоматический сбор цен |
| Хранение результата | Markdown, CSV | Финальный отчёт и таблицы |
4. Этапы выполнения
Этап 1: Сбор и очистка данных (30-40 минут)
Действия
-
Загрузка синтетического датасета (или реального CUR)
import pandas as pd df = pd.read_csv('simulated_usage.csv', parse_dates=['timestamp']) print(df.head(), df.info()) -
Проверка целостности:
- Нет пропусков по времени (если почасовые данные — все часы)
- Корректные типы инстансов
- Цены неотрицательные
-
Агрегация по дням и типам инстансов:
daily = df.groupby([df['timestamp'].dt.date, 'instance_type', 'pricing_model']).agg( total_hours=('usage_hours','sum'), total_cost=('cost','sum') ).reset_index() -
Вычисление базовых метрик:
- Среднее количество часов в день на один инстанс
- Пиковая нагрузка (99-й перцентиль часов в день)
- Доля spot-прерываний (если есть флаг)
Ожидаемый результат этапа DataFrame daily и статистика использования в виде таблицы (среднее, медиана, P90, P99).
Этап 2: Расчёт стоимости для каждой модели покупки (1-1.5 часа)
Действия
-
Получить цены для on-demand (известны из датасета или актуальные):
- p3.2xlarge: $3.06/h
- c5.xlarge: $0.34/h
- p4d.24xlarge: $32.77/h
-
Рассчитать reserved instances (1 год, частичная предоплата):
- Взять коэфициенты: ~40% экономии для 1yr all upfront, ~30% для partial upfront.
- Формула: effective_reserved_cost = (upfront_fee / 8760 + hourly_fee_reserved) * hours_used
- Использовать данные AWS: например, для p3.2xlarge reserved 1yr partial upfront = $1.84/h (vs on-demand $3.06)
- Важно reserved оплачивается полностью, даже если инстанс не используется. Нужно учесть минимальную закупку.
-
Рассчитать spot:
- Средняя цена spot для p3.2xlarge в us-east-1 около $0.92 (30% от on-demand, но может колебаться)
- Учесть прерывания: добавить штраф в 10% времени (перезапуск, потеря прогресса)
- Spot_price = on_demand_price * 0.3 * (1 + interruption_overhead)
-
Для каждого типа инстанса построить три колонки: стоимость, если все часы on_demand; если все reserved; если все spot (с учётом прерываний).
-
Сравнить с фактическими затратами из датасета (смешанная модель).
Ожидаемый результат этапа Таблица цен для каждого типа инстанса по трём моделям (on-demand, reserved, spot). Пример:
| Instance type | On-demand ($/h) | Reserved 1yr ($/h) | Spot ($/h, avg) | Interruption overhead |
|---|---|---|---|---|
| p3.2xlarge | 3.06 | 1.84 | 0.92 | 10% |
| c5.xlarge | 0.34 | 0.20 | 0.10 | 5% |
| p4d.24xlarge | 32.77 | 19.66 | 9.83 | 15% |
Этап 3: Оптимизация комбинации (1.5-2 часа)
Действия
-
Определить ограничения
- Критический ворклоуд (training) не должен прерываться → min 70% reserved.
- Non-critical batch jobs → до 100% spot.
- Dev/test → on-demand или spot.
-
Построить три сценария
- Консервативный: 70% reserved, 20% on-demand, 10% spot.
- Сбалансированный: 40% reserved, 30% on-demand, 30% spot.
- Агрессивный: 20% reserved, 10% on-demand, 70% spot.
-
Для каждого сценария рассчитать общую стоимость за 3 месяца:
- Использовать почасовой лог: для каждого часа и типа инстанса распределить часы между моделями пропорционально сценарию.
- Например, для часа с p3.2xlarge и 0.9 часа использования: 0.9 * (0.7reserved_price + 0.2on_demand_price + 0.1*spot_price).
- Учесть, что reserved часы оплачиваются полностью 24/7, поэтому фиксированная часть = резервирование * 24 * 90 дней.
-
Вычислить метрики
- Total cost
- Savings vs 100% on-demand
- Risk score (вероятность прерывания для критических задач)
-
Визуализация: столбчатая диаграмма сравнения сценариев, круговая диаграмма распределения моделей.
Ожидаемый результат этапа Числовые значения cost для трёх сценариев, таблица метрик, графики.
Этап 4: Рекомендация и отчёт (30-60 минут)
Действия
- Выбрать оптимальный сценарий (например, сбалансированный, если он даёт 40% экономии при приемлемом риске).
- Написать отчёт в формате Markdown, включив:
- Executive summary
- Методология
- Таблица сравнения
- Рекомендуемое соотношение
- План миграции
- Подготовить Python-скрипт
cost_optimizer.py, который принимает на вход CSV с использованием и выдаёт рекомендацию.
Ожидаемый результат этапа Файл report.md и cost_optimizer.py.
Этап 5: Защита решения (опционально, 15 минут)
Действия
- Подготовить 3 слайда (можно в Markdown):
- Исходные данные и текущие затраты
- Сравнение трёх сценариев
- Рекомендация и обоснование
- Ответить на вопросы: почему не 100% spot? как учесть будущий рост?
Ожидаемый результат этапа Готовность к презентации.
5. Критерии приемки (Definition of Done)
- Сгенерирован синтетический датасет (или использован реальный) с колонками timestamp, instance_type, usage_hours, pricing_model, cost.
- Для каждого типа инстанса получены цены on-demand, reserved, spot (можно из статической таблицы).
- Построены и рассчитаны три сценария комбинации моделей.
- Создана таблица сравнения сценариев с total cost и savings.
- Написан Python-скрипт, воспроизводящий расчёт при новых данных.
- Оформлен Markdown-отчёт с executive summary и рекомендацией.
- Код скрипта закомментирован и содержит docstrings.
- Все графики (хотя бы один) сохранены в PNG в папке
figures/.
6. Ожидаемый результат
Основной артефакт — файл report.md следующего содержания:
# Cost Optimization Report for ML Infrastructure
## Executive Summary
Рекомендуется сценарий "сбалансированный": 40% reserved, 30% on-demand, 30% spot.
Экономия относительно 100% on-demand: 38%.
## Исходные данные
- Период: 3 месяца
- Средняя загрузка: 45%
- Основные типы инстансов: p3.2xlarge, c5.xlarge, p4d.24xlarge
## Сценарии
| Сценарий | Reserved | On-demand | Spot | Total cost | Savings |
|----------------|----------|-----------|-------|------------|---------|
| Conservative | 70% | 20% | 10% | $XX,XXX | 25% |
| Balanced | 40% | 30% | 30% | $XX,XXX | 38% |
| Aggressive | 20% | 10% | 70% | $XX,XXX | 45% (risk) |
## Рекомендация
- Закупить reserved на 40% от baseline (по типу p3.2xlarge и p4d.24xlarge)
- Остальное: on-demand для critical jobs, spot для batch
- План миграции: в течение 2 недель
## Приложение: Код расчёта
Ссылка на `cost_optimizer.py`
Дополнительно:
cost_optimizer.py— скрипт с функциейoptimize(usage_csv, pricing_dict).figures/— папка с графиками.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Нет реальных данных по прерываниям spot | Заложить фиксированный overhead (10-15%) на основе документации AWS |
| Разные регионы с разными ценами | Ограничиться одним регионом (us-east-1) для упрощения |
| Reserved предполагает предоплату, сложно учесть NPV | Использовать упрощённую модель: амортизировать upfront на срок (1 год / 8760 часов) |
| Сложность в распределении часов по сценариям | Использовать подход Monte Carlo: для каждого часа случайно выбрать модель согласно весам, повторить N раз |
| Отсутствие информации о критичности ворклоуда | Ввести параметр critical_fraction (по умолчанию 0.3) |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| 1: Сбор и очистка данных | 0.5 ч |
| 2: Расчёт стоимости моделей | 1.5 ч |
| 3: Оптимизация комбинации | 2 ч |
| 4: Рекомендация и отчёт | 1 ч |
| 5: Защита (опционально) | 0.25 ч |
| Итого (рабочее) | 5.25 ч |
Примечание для первого раза Добавьте 1 час на развертывание окружения и понимание AWS Pricing. Итого ~6.5 ч.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| Q42 | Основы cost engineering в облаке |
| Q58 | Reserved Instances vs Savings Plans |
| Q73 | Spot instance best practices для ML |
| Q104 | Мониторинг затрат в AWS |
| Q127 | TCO калькулятор для GPU |
| Q161 | Практика: анализ billing-отчёта |
| Q203 | Оптимизация cost для batch jobs |
| Q288 | Риски spot-прерываний и mitigation |
| Q314 | Использование AWS Price List API |
| Q401 | Построение дашборда cost в Grafana |
10. Чек-лист самопроверки
- Я корректно сгенерировал синтетический датасет и проверил его на аномалии.
- Я взял актуальные цены для выбранного региона (или использовал статическую таблицу из задания).
- Я рассчитал стоимость reserved с учётом амортизации upfront.
- Я учёл overhead spot-прерываний при расчёте общей стоимости.
- Я построил как минимум один график, демонстрирующий сравнение сценариев.
- Мой Python-скрипт корректно принимает новый CSV и выдаёт рекомендацию.
- Отчёт
report.mdсодержит все обязательные разделы и читаем без дополнительных пояснений.