Полностью оптимизированная практика для сбоев обновления модели TensorFlow Serving.

TensorFlow

предисловие

В рекомендуемом сценарии алгоритма оценки CTR (Click Through Rate) при использовании Tensorflow Serving для горячего обновления большой модели произойдет сбой с короткой задержкой, что приведет к тайм-ауту на стороне бизнеса и уменьшит эффект алгоритма. Чтобы решить эту проблему, iQIYI После нескольких этапов практики оптимизации команда платформы глубокого обучения, наконец, тщательно оптимизировала исходный код TF Serving и Tensorflow, чтобы устранить явление сбоя при горячем обновлении модели.В этой статье будет рассказано об оптимизации подробности о Tensorflow Serving, надеясь помочь всем.

Введение

Tensorflow ServingЭто высокопроизводительная система вывода с открытым исходным кодом Google для развертывания моделей машинного обучения. В основном он имеет следующие характеристики:

- поддерживает интерфейсы gRPC и HTTP

- Поддерживает несколько моделей, несколько версий

- Поддержка горячего обновления модели и переключения версий

Большое количество сервисов рекомендаций CTR на платформе глубокого обучения iQiyi используют Tensorflow Serving для развертывания онлайн-сервисов рассуждений.

Сервисы CTR предъявляют высокие требования к устойчивости онлайн-сервисов.Недопустимо прерывать сервис при обновлении модели.Поэтому функция горячего обновления модели TF Serving оказывает большую помощь в таких бизнес-сценариях и позволяет избежать перезапусков.Контейнеры для апгрейды модели.

Однако, поскольку бизнес требует все более и более высоких обновлений модели в реальном времени, мы обнаружили, что явление кратковременного ожидания запроса клиента (так называемое явление сбоя) во время горячего обновления модели стало относительно важным фактором для дальнейшего повышения производительности в реальном времени. препятствие.

Глюк при обновлении модели

Давайте сначала посмотрим,

Что за явление глюка при обновлении модели?

Следующее изображение — это то, что мы добавили в код TF Serving.Bvarчтобы увидеть задержку внутренних запросов. Цифра представляет собой квантильный коэффициент задержки, а значения квантиля задержки соответственно[p80, p90, p99, p999], в микросекундах.

Как видно из рисунка, до и после обновления модели,p999задержки30msследующее. Однако в момент обновления моделиp999Задержка внезапно дрожит120ms+, который длился около 10 секунд, это ** явление сбоя **, и ответ клиенту приведет к сбою тайм-аута запроса.

Чтобы полностью решить эту проблему, платформа глубокого обучения iQIYI прошла несколько этапов глубокой оптимизации и, наконец, устранила явление сбоя при обновлении модели.

Процесс обновления модели TF Serving

Если вы хотите преуспеть, вы должны сначала отточить свои инструменты.Давайте сначала посмотрим на процесс обновления модели внутри TF Serving.

Как показано выше,SourceБудет запущен поток для непрерывного просмотра файла модели, а затем будет построена новая найденная модель.Servableструктура данных вAspired Versionsв очереди.

DynamicManagerОн также запустит поток для проверкиAspired VersionsЕсть ли в очереди запросы, которые необходимо обработать, в соответствии с конфигурациейVersion Policyдля выполнения стратегии обновления модели и, наконец, передатьSessionBundleвыполнять загрузку и выгрузку модели.

Version PolicyПо умолчаниюAvailabilityPreservingPolicy, особенностью этой политики является то, что при добавлении новой модели она гарантирует наличие хотя бы одной работоспособной версии модели.При загрузке новой версии старая версия будет удалена, что может обеспечить работоспособность модели в наибольшей степени.

Например, если поддерживается только одна версия модели, а текущая версия — 2, при добавлении новой версии 3 сначала будет загружена версия 3, а затем версия 2 будет удалена.

Далее давайте подробно рассмотрим процесс загрузки модели TF Serving, который в основном разделен на следующие этапы:

  1. Создать сеанс DirectSession

  2. Загрузите график модели в сеанс

  3. Выполните операцию восстановления на графике, чтобы прочитать переменные из модели в память.

  4. Выполните Init Op в Graph, чтобы выполнить инициализацию связанной модели.

  5. Если настроен прогрев, выполните операцию прогрева, чтобы прогреть модель с определенными образцами.

Очень существенной особенностью выполнения модели Tensorflow является ленивая инициализация, то есть, если нет Warmup, когда TF Serving заканчивает загрузку модели, он загружает только Graph и переменные, OP в Graph фактически не инициализируется, только когда client first OP будет инициализирован только при отправке запроса.

Предварительная оптимизация задачи

‍Из вышеприведенного анализа мы можем увидеть предварительное решение, заключающееся в прогреве модели. Конкретное решение выглядит следующим образом:

  1. Настройте прогрев модели и добавьте файл tf_serving_warmup_requests в каталог модели.

  2. Используйте независимые потоки для загрузки и выгрузки моделей, настройкиnum_unload_threadsиnum_load_threads

Для получения подробной информации о том, как прогреть модель, обратитесь к документации TF.SavedModel Warmup. ](woohoo.tensorflow.org/burst/serving…)

Вторая оптимизация в основном относится к статье Meituan.Онлайн-прогнозирование глубокого обучения на основе TensorFlow Serving.

Сравним разницу до и после оптимизации: ‍

Видно, что при использовании вышеописанной оптимизации задержка джиттера снижается на несколько порядков, и эффект очевиден.

Дальнейшая оптимизация задачи ·

Хотя приведенная выше оптимизация уменьшает сбой при обновлении модели до 120 мс+, это все равно приведет к тайм-ауту запроса клиента.Если частота обновления модели не высока, например, один раз в день, это в принципе приемлемо.

Однако, если производительность обновления бизнес-модели в режиме реального времени составляет час или даже выше, проблема сбоя должна быть дополнительно решена. Мы должны продолжать думать, в чем причина этого оставшегося глюка?

TF Serving требует больших вычислительных ресурсов. Мы сделали следующие предположения о факторах, которые могут повлиять на это:

  • Причина расчета: повлияла ли инициализация новой модели, включая расчет прогрева, на запрос логического вывода?

  • Причины памяти: это вызвано выделением или освобождением памяти в процессе обновления модели для создания блокировок?

  • Или оба?

Расчет Причина Анализ

Давайте сначала проанализируем причины расчета.Если загрузка модели повлияет на запрос вывода, может ли загрузка модели также выполняться в отдельном потоке?

Изучив исходный код TF Serving, мы нашли такие параметры, оказывается, TF учла такие факторы.


  // If set, session run calls use a separate threadpool for restore and init

  // ops as part of loading the session-bundle. The value of this field should

  // correspond to the index of the tensorflow::ThreadPoolOptionProto defined as

  // part of `session_config.session_inter_op_thread_pool`.

  google.protobuf.Int32Value session_run_load_threadpool_index = 4;

по конфигурацииsession_inter_op_thread_poolи установитьsession_run_load_threadpool_indexИнициализацию модели можно поместить в отдельный поток.

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

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

Таким образом, механизм потоков обслуживания TF подвергается дальнейшему анализу, и обнаруживается, что вычислительная часть в основном сосредоточена в потоках Inter и Intra Op TF.После того, как поток инициализации модели станет независимым, исходный запрос вывода не будет затронут.

Кроме того, после анализа было обнаружено, что TF создаст дополнительный пул потоков для восстановления больших переменных при выполнении Restore Op, поэтому я попытался удалить пул потоков во время Restore и обнаружил, что это по-прежнему не дает никакого эффекта.

Анализ причин памяти

Давайте взглянем на механизм выделения памяти TF.Память графического процессора TF выделяется с помощью алгоритма BFC (наилучшее соответствие с объединением), а выделение памяти ЦП заключается в непосредственном вызове базового выделения памяти glibc ptmalloc2.

В настоящее время бизнес CTR на платформе в основном зависит от процессора, поэтому выделением и освобождением памяти управляет glibc ptmalloc2.

После расследования мы узнали, что управление памятью Linux glibc также оптимизировано.Первоначальная реализация — dlmalloc, которая плохо поддерживает многопоточность.Теперь ptmalloc2 оптимизирован для поддержки многопоточности.

Если вы хотите углубиться в ptmalloc2 для оптимизации управления памятью, это более проблематично, но исследование показало, что уже существует решение для оптимизации с открытым исходным кодом, то есть Google.Tcmallocи FacebookJemalloc.

Преимущества и недостатки Ptmalloc, Tcmalloc и Jemalloc В Интернете есть много статей, в которых анализируются преимущества и недостатки Ptmalloc, и все они указывают на то, что Tcmalloc и Jemalloc имеют лучшую производительность в многопоточной среде для уменьшения конкуренции за блокировки.

Было проведено сравнение и тестирование трех распределителей памяти, и результаты экспериментов следующие:

По результатам эксперимента, Tcmalloc и Jemalloc лучше подавляют сбои, но Tcmalloc увеличивает задержку p999 в нормальных условиях; с другой стороны, сбой p999 Jemalloc снижается до менее 50 мс, а p999 в нормальных условиях также оптимизирован, чем Ptmalloc.

Кажется, что Jemalloc является относительно идеальным решением, но в дальнейших экспериментах было обнаружено, что если две версии обновляются одновременно, сбой p999 Jemalloc будет достигать почти 60 мс, и после этого будет относительно длительный период джиттера задержки. обновление, которое продлится почти минуту, как показано ниже:

На данном этапе оптимизации, если вы не чувствительны к таким изменениям задержки, вы в принципе можете использовать Jemalloc как решение для выхода в интернет, но этот эффект еще не очень идеален, поэтому проводится более глубокая оптимизация.

Окончательная глубокая оптимизация задачи

Эффект оптимизации приведенной выше схемы памяти дает хорошее вдохновение и направление.Основная причина сбоя должна быть в распределении памяти и конкуренции за выпуск, поэтому давайте подробнее проанализируем выделение памяти TF.

Сценарии использования выделения и освобождения памяти TF в основном делятся на две части:

  • Частично это выделение самой переменной Tensor при восстановлении модели, которая выделяется при загрузке модели, а память освобождается при выгрузке модели

  • Частью этого является промежуточный вывод выделения памяти Tensor во время прямого расчета сети во время RPC-запроса, который освобождается после обработки запроса.

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

Во время этого процесса запрос RPC не прерывается, в это время выделение и освобождение памяти вызовет конфликт и конкуренцию.

**Поэтому разработана **схема изоляции выделения памяти ****:

Изолируйте выделение памяти параметров самой модели и выделение памяти в процессе запроса RPC, чтобы их выделение и освобождение находились в разных пространствах памяти.

В сочетании с обновлением модели в одном контейнере онлайн-модели находится не более двух версий файлов модели, и для каждой версии модели выделяется независимый пул памяти для переключения AB.

С точки зрения написания кода, у TF просто есть готовый распределитель памяти BFC, который использует BFC в качестве распределителя памяти для параметров модели.Распределение памяти, запрошенное RPC, по-прежнему использует glibc ptmalloc2 для равномерного распределения, поэтому окончательный дизайн выглядит следующим образом:

Изменения кода в основном в исходном коде TF, в основном дляProcessState,ThreadPoolDeviceиAllocatorВнес некоторые изменения.

Наконец, давайте посмотрим на результаты теста:

Из рисунка видно, что после обновления модели джиттер задержки очень мал, около 2 мс, а в пиковом периоде фактического онлайн-теста джиттер составляет около 5 мс, что соответствует потребностям бизнеса.

Суммировать

В этом документе представлена ​​оптимизация проблемы сбоя TF Serving с помощью платформы глубокого обучения iQIYI, которая в основном резюмируется следующим образом:

  1. Настройте файл прогрева модели для первоначального прогрева модели.

  2. Оптимизация распределения памяти с использованием Jemalloc

  3. Распределение параметров модели TF и ​​разделение выделения памяти для запросов RPC

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

использованная литература

  1. TF Serving Aarchtecture: GitHub.com/tensorflow/…

  2. BVar: GitHub.com/Apache/Inc U…

  3. TF WarmUp: woohoo.tensorflow.org/burst/serving…

  4. Онлайн-прогноз Meituan о глубоком обучении на основе TensorFlow Serving:Специальности.Meituan.com/2018/10/11/…

  5. Гугл Tcmalloc:О, о, мальчик - perf tools.source forge.net/doc/TC mall O…

  6. Facebook Jemalloc: jemalloc.net/