Перейти к содержанию
Данные и AI

12 вопросов по теме «ML Engineering: Сервинг и инфраструктура» на собеседовании

В этом материале — 12 вопросов из русской колоды RecallDeck по теме «ML Engineering: Сервинг и инфраструктура». Сначала сформулируйте короткий ответ сами, затем откройте подробный разбор и проверьте примеры, ограничения и отказные случаи.

9 мин чтения12 подробных ответовПроверено 24 августа 2026
Главная мысль

Сначала зафиксируйте grain данных, допущения, метрику и риск leakage, затем обсуждайте модель, инструмент или инфраструктуру.

Вопросы и ответы

12 подробных ответов

01

Онлайн- vs батч-инференс: когда какой выбирать?

Короткий ответ: Батч-инференс — предсказания считаются заранее по расписанию и складываются в хранилище; онлайн — модель отвечает на запрос в реальном времени. Выбор определяется двумя вопросами: известны ли входы заранее и как быстро предсказание устаревает.

Подробно:

Батч Онлайн
Когда входы известны заранее (ночные рекомендации всем юзерам) фичи появляются только в момент запроса (поисковая строка, корзина)
Латентность не критична; отдаём готовое из KV за миллисекунды жёсткий SLA на p99
Цена дёшево: оффлайн-джоба, спотовые GPU дорого: реплики 24/7 под пиковый трафик
Слабость предсказания устаревают между запусками сложность и хрупкость инфраструктуры

Стандартный гибрид: батчем предрассчитываем кандидатов и эмбеддинги, а онлайн гоняем только лёгкий реранкер на свежих фичах запроса.

⚠️ Частая ошибка: тащить всё в онлайн «для свежести». Если предсказание можно посчитать заранее — батч почти всегда дешевле, проще и надёжнее.

02

Латентность vs пропускная способность в сервинге: как батчинг разменивает одно на другое?

Короткий ответ: Батчинг повышает пропускную способность GPU ценой латентности отдельного запроса: запросы ждут в очереди, пока наберётся батч. SLA формулируют по p99, а не по среднему — именно хвост страдает первым.

Подробно:

  1. GPU — устройство для throughput — forward на batch=1 использует единицы процентов FLOPS; матричные ядра простаивают, деньги горят.
  2. Числовой пример — forward: batch=1 → 10 мс, batch=32 → 40 мс. Throughput вырос с 100 до 800 RPS (×8), но запрос, пришедший в батч первым, ждёт добора: латентность с 10 мс уезжает к 40+ мс.
  3. p99, а не среднее — среднее может выглядеть прилично, пока запросы, попавшие в неудачный батч-цикл, пробивают SLA.
batch=1 : 10 мс/forward → 100 RPS, латентность ~10 мс
batch=32: 40 мс/forward → 800 RPS, латентность 40+ мс (очередь!)

⚠️ Частая ошибка: оптимизировать среднюю латентность. Пользователь и SLA живут в p99 — при батчинге хвост растёт первым.

03

Что такое динамический батчинг (например, в Triton Inference Server)?

Короткий ответ: Сервер сам накапливает входящие запросы в очередь и собирает их в один батч: либо набрался max_batch_size, либо истёк max_queue_delay — и батч уходит в один forward. Клиенты шлют по одному запросу, GPU видит батчи.

Подробно:

  1. Две ручкиmax_batch_size (потолок размера) и max_queue_delay_microseconds (сколько ждать добора). Delay — прямая надбавка к латентности каждого запроса.
  2. Что даёт — утилизация GPU и throughput растут в разы без изменения клиентского кода.
  3. Цена — хвост — при неровном трафике запрос может провисеть весь delay и уйти в большой батч: p99 растёт заметно быстрее p50.
  4. Когда НЕ включать — жёсткий p99-бюджет без запаса; рантайм, оптимизированный под batch=1; трафик настолько редкий, что батчи не набираются — тогда delay в чистый минус.
запросы ──► очередь ──► [набралось 32 ИЛИ прошло 5 мс] ──► один forward

⚠️ Частая ошибка: выкрутить max_queue_delay ради красивого throughput в бенчмарке — и молча подарить каждому боевому запросу лишние миллисекунды латентности.

04

REST vs gRPC для сервинга моделей — почему на model path обычно gRPC?

Короткий ответ: gRPC — стандарт на внутреннем model path: HTTP/2, бинарная сериализация protobuf (дёшево на тензорных payload'ах), нативный стриминг и мультиплексирование соединений. REST оставляют внешним клиентам и отладке.

Подробно:

REST/JSON gRPC
Сериализация текстовый JSON — дорого на массивах float бинарный protobuf
Транспорт HTTP/1.1, соединение на запрос HTTP/2, мультиплексирование
Стриминг костыли (SSE, chunked) нативный, в обе стороны
Отладка curl и глаза нужен tooling и .proto-схемы
Клиенты любой браузер codegen из .proto

Разница ощутима, когда сериализация сопоставима с самим инференсом: маленькая модель, большие тензоры, тысячи RPS.

⚠️ Частая ошибка: «переедем на gRPC — станет быстрее». Если модель отвечает 200 мс, экономия пары миллисекунд на транспорте не решает ничего. Транспорт важен при миллисекундном инференсе и жирных payload'ах — знать, когда именно, и есть ответ.

05

Зачем фича-стору онлайн- и оффлайн-контур?

Короткий ответ: Оффлайн-контур (warehouse/Parquet) отдаёт фичи для обучения — большие исторические выборки с point-in-time-корректными джоинами. Онлайн-контур (Redis/KV) отдаёт те же фичи на инференс за миллисекунды. Смысл в том, что одно определение фичи материализуется в оба контура — это и убивает training-serving skew.

Подробно:

  1. Оффлайн — объёмные исторические срезы; главное — point-in-time correctness: значение фичи на момент события, без утечки будущего.
  2. Онлайн — key-value с чтением за единицы миллисекунд по ключу сущности (user_id, item_id).
  3. Одно определение — фича описана один раз (SQL/DSL), пайплайн материализует её и в warehouse, и в KV: трейн и сервинг видят одну и ту же логику.
  4. Freshness SLA на фичу — «покупки за 30 дней» можно обновлять раз в сутки, «клики за 5 минут» — только стримом; бюджет свежести задаётся per-feature.
                  ┌─► offline store (Parquet) ─► трейн (point-in-time джоины)
определение фичи ─┤
                  └─► online store (Redis/KV) ─► инференс (< 10 мс)

⚠️ Частая ошибка: считать фича-стор «базой для фичей». Его ценность не в хранении, а в единственном определении фичи, из которого собираются оба контура.

06

Спроектируйте сервинг ранжирующей модели на 10k QPS с p99 < 100 мс. С чего начнёте?

Короткий ответ: С бюджета латентности по хопам. Дальше: разделить candidate generation и ранжирование, забирать фичи одним батч-запросом, кэшировать, масштабироваться stateless-репликами за LB и заранее договориться о graceful degradation. 10k QPS — это про архитектуру вокруг модели, а не про модель.

Подробно:

p99-бюджет 100 мс:
  LB + сеть              ~5 мс
  фичи из онлайн-стора   ~15 мс (mget в Redis, один RTT!)
  candidate gen (ANN)    ~15 мс (top-500)
  ранкер forward         ~40 мс (батч из 500 кандидатов)
  сериализация + ответ   ~10 мс
  запас на хвост         ~15 мс
  1. Два этажа — дешёвый retrieval сужает миллионы до сотен, тяжёлый ранкер скорит только их.
  2. Фичи одним запросом — mget/pipeline; N последовательных RTT съедят весь бюджет.
  3. Кэш — фичи горячих сущностей и готовые скоры популярных запросов.
  4. Реплики — stateless-сервинг за LB, autoscaling по QPS и p99.
  5. Degradation — таймаут ранкера → отдать кандидатов по популярности или кэшированные скоры, а не 500-ку.

⚠️ Частая ошибка: отдать весь бюджет модели и «вспомнить» про сетевые RTT за фичами — а они легко съедают 20–30 мс.

07

Модель отвечает за 200 мс, а SLA — 50 мс. Какие у вас варианты?

Короткий ответ: Уменьшать работу на запрос: дистилляция или квантизация модели, каскад (лёгкая модель фильтрует, тяжёлая скорит top-k), предрасчёт и кэш для популярных сущностей, асинхронные частичные ответы. «Купить больше GPU» не вариант: реплики лечат throughput, а не латентность одного запроса.

Подробно:

Опция Что даёт Что стоит
Дистилляция маленькая модель с близким качеством цикл обучения, небольшая потеря метрик
Квантизация (INT8/FP8) ×2–4 к скорости forward риск деградации — нужен eval до и после
Каскад тяжёлая модель только на top-k от лёгкой двухступенчатый пайплайн, тюнинг порога
Предрасчёт + кэш хиты отвечают из KV за миллисекунды покрывает только «голову» распределения
Асинхронность быстрый частичный ответ, дообогащение потом продукт должен уметь жить с частичным ответом

⚠️ Частая ошибка: предложить горизонтальное масштабирование. Одиночный запрос всё равно проходит один forward за 200 мс — реплики добавляют параллелизм, а не скорость.

08

Как работает HNSW и в чём его tradeoff против IVF и brute force?

Короткий ответ: HNSW — многослойный navigable-small-world граф: поиск стартует на редких верхних слоях, жадно спускаясь к запросу, и финиширует на плотном нижнем слое — примерно O(log n). Лучший recall при низкой латентности, но граф живёт в RAM. IVF экономит память, brute force точен и достаточен до ~1M векторов.

Подробно:

  1. HNSW — верхние слои как «магистрали» для дальних прыжков, нижний — точная локальная навигация; recall тюнится параметром efSearch: больше — точнее и медленнее.
  2. IVF — корпус кластеризуется (k-means); на запросе сканируем только nprobe ближайших списков. Дешевле по памяти, recall проседает на границах кластеров.
  3. Flat (brute force) — честный скан всех векторов: recall 100%; до ~1M векторов на GPU часто быстрее, чем принято думать.
Recall Латентность Память
HNSW высокий низкая высокая (граф в RAM)
IVF(+PQ) средний средняя низкая
Flat 100% линейно растёт с n средняя

Выбор — треугольник recall–латентность–память: фиксируете два, третьим платите.

⚠️ Частая ошибка: тащить HNSW на 100k векторов «потому что все так делают» — там brute force точнее, проще и уже достаточно быстр.

09

Где в ML-сервинге добавляют кэши и что их инвалидирует?

Короткий ответ: Три слоя: кэш фич (TTL по волатильности фичи), кэш предсказаний (ключ — сущность + версия модели), кэш эмбеддингов (меняются только с ретрейном — долгий TTL). Главный вопрос к любому кэшу в ML-системе — не hit rate, а что именно его инвалидирует.

Подробно:

Кэш Что кэшируем Что инвалидирует
Фич значения из онлайн-стора TTL по волатильности; событие изменения сущности
Предсказаний скоры для повторяющихся входов новая версия модели (она в ключе!), TTL
Эмбеддингов векторы айтемов/юзеров ретрейн — до него вектор статичен
  1. TTL от волатильности — демография живёт днями; счётчик кликов за 5 минут кэшировать почти нельзя.
  2. Версия модели в ключе — выкатка новой версии автоматически инвалидирует кэш предсказаний; иначе часть трафика молча получает скоры старой модели.
  3. Событийная инвалидация — обновился профиль → выкинуть его фичи, не дожидаясь TTL.

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

10

Что хранится в model registry и как модель попадает в прод?

Короткий ответ: Версионированный артефакт плюс родословная: хэш данных, git-коммит, конфиг, метрики оффлайн-eval. Путь в прод — переходы по стейджам (staging → production), откат — переставить алиас на предыдущую версию, без пересборки.

Подробно:

  1. Артефакт + lineage — по любой продовой версии восстановимо: на каких данных училась (data hash), каким кодом (commit), с каким конфигом и какие метрики показала.
  2. Стейджи и алиасыstaging → smoke-тесты и шедоу → production; сервинг тянет модель по алиасу (prod), а не по номеру версии.
  3. Откат — repoint алиаса на прошлую версию: секунды, без redeploy сервиса.
  4. Модель и фичи версионируются вместе — новая версия ждёт другой набор фич; рассинхрон конфига фич и артефакта — классическая тихая поломка.
train run ─► registry: v42 + lineage (data hash, commit, config, метрики)
v42: staging ──smoke/shadow──► prod (алиас)
rollback = переставить алиас prod → v41

⚠️ Частая ошибка: «модель лежит у нас в S3». Файл .pt без lineage и стейджей — красный флаг для интервьюера: такую модель ни воспроизвести, ни безопасно откатить.

11

Как выкатить новую версию модели на уровне трафика?

Короткий ответ: Лестница: shadow (дублируем запрос новой версии асинхронно, ответ не возвращаем — валидируем латентность и адекватность скоров) → канарейка на 1–5% → расширение по sticky-сплиту (consistent hashing по user id). На каждой ступени — метрики выхода и заранее записанный триггер отката.

Подробно:

shadow (0% решений) ─► canary 1–5% ─► 25% ─► 100%
        │                  │           │
        └──────────────────┴───────────┴─► rollback: алиас на v-1
  1. Shadow — новая версия видит боевой трафик, ответы только логируются; всплески латентности, ошибки и дикие распределения скоров ловим до первого пользователя.
  2. Канарейка — 1–5% живых решений; системные метрики и скоры сравниваем с контролем.
  3. Sticky-сплит — consistent hashing по user id, а не случайный выбор на запрос: пользователь не должен прыгать между версиями.
  4. Гигиена логов — в shadow фичи логируются дважды; не пометить источник — задвоить обучающие логи.

Продуктовый эффект меряется A/B-экспериментом — это отдельная механика; здесь только инфраструктурная безопасность выкатки.

⚠️ Частая ошибка: случайный сплит на уровне запросов — один и тот же пользователь получает то старые, то новые скоры, и дебаг превращается в ад.

12

После деплоя p99 вырос вдвое, а p50 не изменился. Где будете искать?

Короткий ответ: Раз p50 стоит на месте — типичный forward жив, деградировал именно хвост. Подозреваемые только «хвостовые»: насыщение очереди батчинга, холодный кэш для редких сущностей, одна больная реплика, GC-паузы, исчерпание тред-пула. Сначала per-hop трейсинг — модель трогаем последней.

Подробно:

Порядок разбора:

  1. Трейсинг по хопам — где именно вырос хвост: очередь, фичи, forward, сеть? Без распределённого трейса всё остальное — гадание.
  2. Одна реплика — p99 по каждой реплике отдельно: одна больная машина (throttling, шумный сосед) портит общий хвост при здоровом p50.
  3. Очередь батчинга — деплой изменил max_queue_delay или подрос трафик: часть запросов ждёт добора батча, и это чистый удар по хвосту.
  4. Холодный кэш — деплой сбросил кэш фич/предсказаний: горячие ключи прогрелись мгновенно (p50 в норме), редкие сущности ходят мимо кэша (p99 растёт).
  5. Рантайм — GC-паузы, исчерпание тред-пула или коннекшн-пула: редкие, но длинные замирания — буквально портрет p99.

⚠️ Частая ошибка: начать с «модель стала медленнее». Если бы forward замедлился, сдвинулся бы и p50 — сама симптоматика исключает модель первым же наблюдением.

Источники

Источники и редакционная политика

Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.

От чтения к воспроизведению

Отрепетируйте полный цикл интервью.

RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.

Начать подготовку

Продолжить подготовку

Библиотека собеседований RecallDeck

Подробные русские ответы, разборы этапов найма и планы подготовки для российского IT-рынка.

RSS