Платформа оценки latency и стоимости ML‑инференса
Внутренний инструмент для профилировки latency, throughput и $/req моделей в проде

One-liner: За 8 недель превратили ML-инфраструктуру из черного ящика в прозрачную и управляемую систему с точной стоимостью каждого запроса.
1. Почему бизнесу была нужна платформа
В начале проекта ML-инфраструктура была разрозненной и неуправляемой:
- Нет единого подхода к деплою моделей: одни команды деплоили через TorchServe, другие использовали ONNX Runtime, третьи работали через KServe.
- Отсутствие прозрачности: никто не понимал точную стоимость одного inference-запроса. GPU простаивали ночью, а днем перегревались, вызывая пиковые скачки latency выше SLA.
- Бюджет горел: инфраструктурная команда временно ограничивала количество нод вручную, чтобы уложиться в лимиты. Иногда это ломало прод, но отследить было невозможно.
2. Что было сделано и зачем
Мы построили универсальный инструмент мониторинга и оптимизации затрат, полностью интегрированный в Kubernetes-среду компании. Платформа собирает все критически важные метрики ML-инфраструктуры:
- Latency: измерение задержек с разбивкой по percentiles (p50, p90, p99).
- Throughput: количество запросов в секунду, деградация при разной нагрузке.
- GPU/CPU-utilization: мониторинг загрузки ресурсов, выявление простоев.
- $/req: точная стоимость каждого ML-запроса на основе Spot API и Kubecost.
Платформа дает actionable-рекомендации:
- замена типа GPU-инстансов (V100 → T4)
- оптимальный batching
- квантизация и pruning моделей
3. Архитектура решения
Платформа мониторинга построена вокруг Kubernetes и сервисов-экспортеров:
Inference-Service (Torch / ONNX)
├── /metrics endpoint (Prometheus-compatible)
│ ├── latency_histogram (p50, p90, p99)
│ ├── throughput_rps
│ └── gpu_utilization / cpu_utilization
│
├── Torch / ONNX Profiler
│ └── performance traces (JSON → Perfetto)
│
└── Kubecost Exporter (via Spot API)
├── spot-instance cost mapping
└── billing aggregation by namespace / model_id labels
↓
┌────────────────────┐
│ Prometheus DB │
└────────────────────┘
↓
┌────────────────┐
│ Alertmanager │ ◄──── SLA breaches (e.g. p99 > 800ms)
└────────────────┘
↓
┌────────────────────┐
│ Grafana Panels │
├────────────────────┤
│ • $/req by model │
│ • p95 latency heat │
│ • throughput trend │
│ • GPU utilization │
└────────────────────┘
↓
Auto-scaling policy input
(via KEDA / HPA / Argo)
Пример метрик в Prometheus:
histogram_quantile(0.99, sum(rate(model_inference_latency_seconds_bucket[5m])) by (le))
Эта метрика вычисляет p99 latency, помогая отлавливать пики и своевременно реагировать на аномалии.
4. Профилировка и нагрузочные тесты
Отдельно были настроены регулярные профилировки моделей:
- PyTorch Profiler: В рамках платформы реализовали отдельный модуль для профилировки latency и ресурсного потребления моделей. Он используется в dev- и CI-средах, чтобы выявлять узкие места после дообучения или при деградации SLA. Ниже приведен пример скрипта, применяемого для такой диагностики. Профили сохраняются в TensorBoard или Perfetto, результаты анализируются вручную или автоматически через threshold-based алерты.
import os
import torch
from contextlib import nullcontext
from torch.profiler import profile, record_function, ProfilerActivity, tensorboard_trace_handler
def run_inference(model, inputs, device):
with torch.no_grad():
with record_function("inference_step"):
return model(inputs)
def get_profiler(log_dir: str, steps: int = 10):
return profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
schedule=torch.profiler.schedule(wait=2, warmup=2, active=steps),
on_trace_ready=tensorboard_trace_handler(log_dir),
record_shapes=True,
profile_memory=True,
with_stack=True,
with_modules=True,
with_flops=True
)
def prepare_inputs(batch_size=32, shape=(3, 224, 224), device="cuda"):
return torch.randn(batch_size, *shape).to(device)
def main():
os.makedirs("./logs", exist_ok=True)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = torch.hub.load("pytorch/vision", "resnet50", pretrained=True).to(device).eval()
inputs = prepare_inputs(device=device)
use_profiler = os.environ.get("ENABLE_PROFILING", "1") == "1"
profiler_ctx = get_profiler("./logs") if use_profiler else nullcontext()
with profiler_ctx as prof:
for step in range(10):
_ = run_inference(model, inputs)
if use_profiler:
prof.step()
if use_profiler:
print(prof.key_averages().table(
sort_by="self_cuda_time_total", row_limit=15))
if __name__ == "__main__":
main()
- ONNX Profiler: для ONNX Runtime использовали tracing API, экспортируя профили в JSON и визуализируя их через Perfetto UI.
Эти профили позволяли увидеть горячие точки в моделях. Например, выделение времени CPU-преобразования (image → tensor → device) занимало до 40% времени inference, что оперативно устранялось.
5. Результаты после запуска платформы
За месяц после запуска платформы получили:
Метрика | До внедрения | После внедрения | Дельта |
---|---|---|---|
Latency p99 | 400–900 мс (нестаб.) | стабильно ~420 мс | стабилизирован |
GPU-utilization | ~36 % | 54 % | +18 pp ↑ |
$/req (на модели LLM) | базовая | -43 % (V100 → T4) | −43 % ↓ |
Точечные алерты | отсутствовали | автоматизированы | внедрено |
Пример реальной ситуации:
- Spot-инстанс упал ночью → платформа сразу отправила алерт и подсветила скачок стоимости в 3 раза → быстро откатили конфигурацию, минимизировав финансовые потери.
6. Почему это важно для бизнеса и технических команд
Платформа изменила подход к работе с ML-инфраструктурой:
- Полная прозрачность: CFO и CTO получили детальную аналитику по стоимости ML-проектов в реальном времени.
- Контролируемые бюджеты: теперь можно открыть Grafana и за 10 секунд узнать: сколько стоил 1M запросов на конкретной модели за сутки
- Управляемый performance: на основе платформы принимаются решения о смене GPU, выборе batch size и запуске retrain при снижении throughput.
Bottom line
За 8 недель мы превратили фрагментированную ML-инфраструктуру в управляемую систему с прозрачными метриками latency, throughput и $/req. Платформа позволила сократить затраты на 43 %, стабилизировать p99 latency и внедрить алерты, срабатывающие при SLA-деградациях и росте стоимости. Теперь каждое решение о запуске модели опирается на цифры на уровне модели, инстанса и бюджета.