- PVSM.RU - https://www.pvsm.ru -

Привет! Я Антон, DevOps-инженер в Selectel. В апреле у нас проходил ML-митап, где я и мой коллега, ML-Ops инженер Ефим Головин [1], рассказали, как подбираем конфигурацию ML-инфраструктуры и повышаем утилизацию GPU. Запись нашего выступления можно посмотреть на YouTube [2]. Материал вышел интересным, поэтому мы решили оформить пересказ в текстовый формат.
В этой статье вы узнаете, как перенести лучшие практики из мира производства в сферу машинного обучения, подобрать конфигурацию вычислительной инфраструктуры под ML-нагрузки и максимально эффективно ее использовать. Впереди много интересного, так что давайте начнем!
Используйте навигацию, если не хотите читать текст полностью:
→ Что можно переиспользовать в ML от заводских промышленных линий [3]
→ Как конфигурировать инфраструктуру под ML-нагрузки [4]
→ Как эффективно утилизировать подобранную конфигурацию ML-инфраструктуры [5]
→ Заключение [6]
Где лучшие тусовки лучше всего отточены технологии и методологии автоматизации? Конечно, на заводах и промышленных предприятиях. Мы вдохновляемся бережливым производством, следуем Кайдзен Toyota, соблюдаем и используем теорию ограничений Голдратта. И переносим этот опыт в разработку ML-систем.
ML-система для конечного клиента — «черный ящик», в котором происходит магия. Он выполняет определенные задачи и выдает результаты на основе входных данных. Клиент взаимодействует с системой через интерфейсы и API, не вникая в сложные внутренние процессы.
Пример такого взаимодействия — распознавание текста на фотографии со знаком «STOP». Это может быть часть системы автономного вождения. Рассмотрим простой пример инференс-графа.

Пример простейшего инференс-графа.
Вот что здесь происходит.
Для клиента вся цепочка представляет собой черный ящик, куда на вход он подает изображение, а на выходе получает слово «STOP». Он не вдается в подробности, как система выглядит изнутри. Аналогично: когда мы покупаем банку кофе в магазине, мы не думаем, как кофе оказался в банке и что за этикетка там наклеена. Мы берем готовый товар и используем его.
Возникает вопрос, нужно ли улучшать работу моделей в инференс-графа, если мы хотим сделать систему эффективнее. На самом деле необходимо рассматривать систему в целом.

Продолжу аналогию с производством: улучшение только одного этапа может не дать значительного эффекта, если не учитывать взаимодействие всех компонентов. Помимо самих инференсов нужно помнить о различных стадиях и компонентах ML-системы. Рассмотрим, как это выглядит с точки зрения MLOps.org.

ML-система от ml-ops.org [7].
Рассмотрим основные компоненты системы:
| Этап MLOps | Результат выполнения этапа |
| Разработка и эксперименты (ML-алгоритмы и ML-модели) | Исходный код для конвейеров: извлечение данных, валидация, подготовка, обучение, оценка и тестирование модели. |
| Непрерывная интеграция конвейера (сборка исходного кода и запуск тестов). | Развертываемые компоненты конвейера: пакеты и исполняемые файлы. |
| Непрерывная доставка конвейера (развертывание конвейеров в целевой среде). | Развернутый конвейер с новой реализацией модели. |
| Автоматизированный триггер (конвейер автоматически выполняется в производстве; используется расписание или триггер). | Обученная модель, которая хранится в реестре. |
| Модель непрерывной доставки (модель, служащая для прогнозирования). | Развернутый инференс. |
| Мониторинг (сбор данных о работе модели на реальных данных). | Триггер для выполнения конвейера или начала нового цикла эксперимента. |
В Nvidia полную схему конвейера видят чуть иначе, хотя ключевые компоненты в основном представлены такие же:

ML-система от AI Infrastructure Alliance. Источник [8].
Используя эти источники, доведем нашу исходную схему до цельного вида:

ML-система в целом.
В итоге помимо самого инференс-графа видим, что в нашей схеме важно учитывать хранилища и конвейеры обучения моделей, а также слой data management. В данном случае все этапы распознавания текста на знаке «STOP» важны для конечного результата, поэтому необходимо рассматривать систему в целом.
Заметили, что мы много говорим про конвейеры? Давайте вспомним, откуда они к нам пришли. Верхнеурово рассмотрим схему конвейера с кафедры Санкт-Петербургского Политехнического университета. Представим, что на нем упаковываются банки кофе.

Тот самый конвейер, где я в студенчестве боролся за зачет.
Конвейерная линия состоит из нескольких этапов, каждый из которых выполняет определенные функции для создания конечного продукта.
На каждой станции будет задержка обработки, потому что требуется время, чтобы насыпать кофе в банку или закрутить крышку. А еще банки передвигаются между станциями — на это тоже тратится время. Здесь возникает задержка транспортировки.
Отмечу, что каждая станция состоит из хардварной и софтварной частей. Хардвар — манипулятор, который перетаскивает банку. Софтвар — алгоритмы, которые вшиты в контроллер. К чему вся эта аналогия, спросите вы? Попробуем перенести эту мысль на ML-системы.
Хотите еще больше аналогий с заводами? Подписывайтесь на мой Telegram-канал [9]. Там я публикую дополнительные материалы по статьям, выступлениям и своим исследованиями в мире ML и DevOps.
Начнем с хардварной части и рассмотрим популярный сервер DGX H100 в качестве хардварной площадки для ML-системы.

Вверху слева — фото платформы DGX H100. Вверху справа — схема материнской платы. Внизу — группировка GPU. Мануал доступен в документации Nvidia. [10]

Логическая схема сервера.
Основные компоненты, которые представлены на логической схеме:
Если выделить общие основные компоненты, из которых состоит сервер и где могут быть задержки, все будет выглядеть примерно так:
| Компонент сервера | Факторы, влияющие на возникновение задержек |
| CPU | Количество процессоров/ядер, их тактовая частота, поддерживаемые инструкции, размер кэшей и т. д. |
| GPU | Количество SM, их тактовая частота, наличие тензорных ядер, объем памяти и т. д. |
| RAM | Объем, пропускная способность, способ подключения и т. д. |
| PCI | Частота, разрядность, пропускная способность и т. д. |
| Storage | Объем, пропускная способность, способ подключения и т. д. |
| Network | Скорость передачи, физическое расстояние до источника данных, наличие RDMA и т. д. |
При этом мы рассматривали сервер on-premise. А что если мы перейдем в облако?

Пример IaaS-платформы на базе OpenStack.
Облако для создания ML-системы дает свои преимущества, но вместе с тем вызывает сложности. Рассмотрим их подробнее.
Преимущества
Сложности
Но это мы говорили про хардварную часть. А что на уровне софта? Вспоминаем наш инференс-граф и ML-систему в целом, особенно пайплайн обучения:

Этапы обучение модели.
На каждом этапе могут быть задержки, которые влияют на систему в целом. И это снова задержки обработки и транспортировки, как на заводе.
Итак, в общих чертах мы разобрались, из чего состоит ML-система, немного копнули в хардварную и софтварную части, а также выясняли, что она похожа на заводские конвейеры (из моей предыдущей статьи [11] можно понять, что я в прошлом заводской работяга). Возникает вопрос: какие минимальные технические требования могут быть предъявлены к этому конвейеру? Попробуем разобраться.
В нашем случае речь идет о данных, на которых мы будем проводить обучение, о моделях, которые мы хотим протестировать, о способах обучения и так далее. То есть нам нужно выбрать, какое минимальное количество ресурсов необходимо, чтобы обучать модели.
Мы опирались на Hugging Face [12] и Coursera [13]. Эти источники детально описывают, куда будет расходоваться память в цикле обучения.
Рассмотрим пример, в котором есть:
Расчеты говорят о том, что на каждый параметр LLM требуется четыре байта видеопамяти. То есть на модель с миллиардом параметров нужно выделить 4 ГБ видеопамяти. Звучит не так уж и страшно.
1 параметр = 4 байта (32-bit float)
1B параметров = 4 x 109 байт = 4 ГБ
Но модель же нужно не только сохранить. Ее еще нужно обучать, поэтому потребуется optimizer, расчет промежуточных значений активационных функций и т. д. Все это добавит еще какое-то количество памяти:
Итого: обучение модели требует дополнительно 20 байт видеопамяти на каждый ее параметр.
И это мы еще не учитываем батч данных, который тоже нужно положить на видеокарту. Сделав несложный расчет, понимаем: чтобы просто обучать модель, нужно иметь 24 ГБ видеопамяти на каждый миллиард ее параметров.

Сравнение требуемой памяти GPU для LLM на 1, 175 и 500 млрд параметров.
Подобный гайд можно использовать, чтобы рассчитать ресурсы для обучения модели: сколько понадобится памяти видеокарты, оперативной памяти, данных для сохранения промежуточных весов сети и данных, на которых будем обучать модель.
Получается, для любых задач просто берем видеокарту помощнее? Нет. Мы рассмотрели достаточно поверхностный и не оптимальный случай. В реальной жизни такой расчет используется только для обучения LLM с нуля.
Если же мы файнтюним модель, можно применить адаптеры [14]. Для инференсов применимы квантизация, дисцилирование и другие способы оптимизации. Подробнее об этом можно почитать в статье Nvidia [15].
Хорошо, мы подобрали минимальную конфигурацию, от которой можно отталкиваться. Что дальше?
Вновь обратимся к заводам. Мне очень нравится книга «Цель» Элияху Голдратта. В ней автор доступно объясняет, как выглядит процесс непрерывного совершенствования на основе теории ограничений. Она предусматривает следующие этапы (распишу с примерами из книги):
На заводах это работает классно! Что ж, применим эту теорию на наших ML-системах? Начнем с поиска узких мест. И в этом нам поможет профайлинг.
Профайлинг — это процесс анализа и оптимизации производительности программного обеспечения. В контексте машинного обучения профайлинг помогает выявлять узкие места в коде, которые замедляют обучение или инференс моделей. Существует несколько инструментов для профайлинга, каждый из которых имеет свои особенности и преимущества.
| Профайлер | Описание | Особенности |
| PyTorch Profiler [16] | Позволяет анализировать производительность моделей, написанных на PyTorch. Предоставляет информацию о затратах времени на выполнение различных операций, что помогает выявить узкие места и оптимизировать код. | Интеграция с TensorBoard для визуализации данных.
Поддержка профайлинга на CPU и GPU. Поддержка анализа данных в формате Chrome Tracing. Для отображения трейсинга лучше использовать Perfetto UI [17] или FlameGraph [18]. |
| TensorFlow Profiler [20] | Инструмент для анализа производительности моделей, созданных на TensorFlow. Помогает оптимизировать обучение и инференс, предоставляя подробные отчеты о производительности. | Визуализация данных в TensorBoard.
Анализ использования памяти и вычислительных ресурсов. Поддержка различных профайлинговых режимов для детального анализа. Как и с PyTorch, для отрисовки используем TensorBoard + TF Profiler [21]. |
| NVIDIA Nsight Systems [22] | Инструмент для системного профайлинга, который предоставляет подробные данные о производительности всего приложения. Помогает выявлять узкие места на уровне системы и оптимизировать использование ресурсов. | Подробный анализ производительности CUDA-ядер.
Поддержка различных метрик и визуализация данных. Интеграция с другими инструментами NVIDIA. |
| NVIDIA Deep Learning Profiler (DLProf) [23] | Инструмент для высокоуровневого профайлинга моделей глубокого обучения. Помогает оптимизировать обучение и инференс, предоставляя отчеты о производительности и использовании ресурсов. | Высокоуровневый анализ производительности моделей глубокого обучения.
Интеграция с Nsight Systems для детального анализа. Поддержка анализа данных в TensorBoard. |
| eBPF [24] (Extended Berkeley Packet Filter) | Технология для анализа производительности на уровне ядра операционной системы.
Позволяет собирать данные о производительности системы в реальном времени и помогает выявлять узкие места в коде. |
Низкоуровневый анализ производительности.
Поддержка реального времени. Интеграция с различными инструментами для анализа данных. |
Отлично, мы нашли узкие горлышки в нашей системе. Дальше по теории ограничений необходимо максимально эффективно утилизировать их.
Посмотрим на типичные узкие горлышки в конвейере обучения.

Больше всего, конечно, хочется сказать про Preprocess и Train. Допустим, мы решаем CV-задачу, где нужно часто играться с изображениями: покрутить, повертеть, наложить фильтры и т. д. В фреймворке MMCV [25] такие трансформации выполняются на CPU. Но в это время процессор простаивает, а это самый дорогой ресурс, который хочется использовать рационально.
Поэтому если можно вынести что-то из цикла тренировки модели, мы это делаем. А если не получается, то хотя бы пробуем перенести трансформации с CPU на GPU.

Кстати, для такой задачи могут быть полезны инструменты из экосистемы RAPIDS [26] от Nvidia. Например, фреймворк QDF, который позволяет работать с табличными данными. Или, если необходимо работать с изображениями, то можно использовать Data Loading Library от NVIDIA [27]. С ее помощью можно составлять пайплайны с трансформациями: повернуть, развернуть, обрезать, центровать и т. д.
Итак, выстраиваем обучение LLM, вдохновившись заводом. То есть ставим дополнительный конвейер. Параллелить обучение можно различными способами, например с помощью Data Parallelism [28].
Мы обучили модель. Теперь нужно обернуть ее в удобный интерфейс, чтобы клиенту было комфортно работать с LLM. Подойдет, например, gRPC или HTTP веб-сервер. Его можно написать самостоятельно, взяв Flask или Fast API. А можно взять готовое open source решение Triton Server [29] — ребята из Nvidia точно знают, как по максимуму утилизировать в инференсе свои GPU.

Архитектура Triton Server.
Оптимизация моделей + правильно подобранная конфигурация Triton Server = максимальная утилизация инференса на инфраструктуре. Triton позволяет настроить динамический батчинг запросов, который увеличивает пропускную способность сервера. Мы получили следующие результаты на небольшой модели:

Так же можно конвертировать модель в различные форматы:

Схема возможных конвертаций моделей.
Когда один Triton Server не будет справляться, применим лайфхак с завода — поставим еще одну реплику. Но для инференсов не нужно иметь мощные GPU, так как мы можем сжимать модели (вспомним пример выше, где на миллиард параметров модели занимает 4 ГБ).
Соответственно, возникает вопрос: как параллельно запустить несколько инференсов на одной GPU? Ответ вы найдете в цикле моих статей про шеринг GPU:
Сейчас же рассмотрим возможные решения:
| Технология | Архитектура GPU | Изоляция памяти | Максимальное количество реплик |
| MIG | Nvidia Ampere + | Изоляция памяти на уровне железа | Семь партиций максимум на A100 |
| MPS | Nvidia Volta + | Изоляция памяти на уровне CUDA | 48 потоков максимум |
| TimeSlicing | Nvidia GPU | Нет изоляции по памяти | Любое количество |
При этом Triton Server внутри одной реплики также может управлять различными моделями. Если он справляется с нагрузкой, можно деплоить LLM в один сервер. Как только перестает справляться, начинаем параллелить реплики.
Возможно, вы задаетесь вопросом: зачем было вообще рассказывать про заводы и производства в материале об ML? Отвечу вам цитатой из книги «Совершенный код» С. Макконнелла:
«Проведение аналогий часто приводит к важным открытиям. Сравнив не совсем понятное явление с чем-то похожим, но более понятным, вы можете догадаться, как справиться с проблемой».
ML-системы достаточно сложны и объемны. Подбор конфигурации и ее максимальная утилизация — нетривиальные задачи. Универсального алгоритма для этого пока нет, но решение конкретной проблемы всегда можно найти в дискуссии. Приглашаю вас в комментариях обсудить, как вы подбираете конфигурацию инфраструктуры и утилизируете ее в своих задачах.
И напоследок поделюсь небольшими рекомендациями и источниками:
Обучение
Инференс
Автор: Антон Алексеев
Источник [52]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/392402
Ссылки в тексте:
[1] Ефим Головин: https://habr.com/ru/users/feanoref/
[2] на YouTube: https://slc.tl/5wbc5
[3] Что можно переиспользовать в ML от заводских промышленных линий: #1
[4] Как конфигурировать инфраструктуру под ML-нагрузки: #2
[5] Как эффективно утилизировать подобранную конфигурацию ML-инфраструктуры: #3
[6] Заключение: #4
[7] ml-ops.org: https://ml-ops.org/content/mlops-principles
[8] Источник: https://blogs.nvidia.com/blog/what-is-mlops/
[9] Telegram-канал: https://t.me/easy_dev_ops
[10] в документации Nvidia.: https://docs.nvidia.com/dgx/dgxh100-user-guide/dgxh100-user-guide.pdf
[11] предыдущей статьи: https://habr.com/ru/companies/selectel/articles/803883/
[12] Hugging Face: https://huggingface.co/docs/transformers/model_memory_anatomy
[13] Coursera: https://www.coursera.org/learn/generative-ai-with-llms/lecture/gZArr/computational-challenges-of-training-llms
[14] адаптеры: https://huggingface.co/docs/peft/index
[15] в статье Nvidia: https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/
[16] PyTorch Profiler: https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html
[17] Perfetto UI: https://perfetto.dev/docs
[18] FlameGraph: https://www.brendangregg.com/flamegraphs.html
[19] PyTorch Profiler TensorBoard Plugin: https://github.com/pytorch/kineto/blob/main/tb_plugin/README.md
[20] TensorFlow Profiler: https://www.tensorflow.org/guide/profiler?hl=ru
[21] TF Profiler: https://github.com/tensorflow/profiler
[22] NVIDIA Nsight Systems: https://developer.nvidia.com/nsight-systems
[23] NVIDIA Deep Learning Profiler (DLProf): https://docs.nvidia.com/deeplearning/frameworks/dlprof-user-guide/index.html
[24] eBPF: https://ebpf.io/
[25] MMCV: https://github.com/open-mmlab/mmcv
[26] RAPIDS: https://developer.nvidia.com/rapids
[27] Data Loading Library от NVIDIA: https://developer.nvidia.com/dali
[28] Data Parallelism: https://docs.nvidia.com/nemo-framework/user-guide/latest/nemotoolkit/features/parallelisms.html
[29] Triton Server: https://github.com/triton-inference-server/server
[30] Практическое пособие по работе с MIG: https://habr.com/ru/companies/selectel/articles/748544/
[31] ШерингGPU с помощью MIG и : https://habr.com/ru/companies/selectel/articles/756934/
[32] Динамический шеринг GPU в Kubernetes с помощью MIG, MPS и : https://habr.com/ru/companies/selectel/articles/776132/
[33] «Архитектура компьютера: https://www.litres.ru/book/endru-tanenbaum/arhitektura-komputera-66738078/
[34] Quantization: https://huggingface.co/docs/transformers/main/en/quantization/overview
[35] A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes: https://huggingface.co/blog/hf-bitsandbytes-integration
[36] Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA: https://huggingface.co/blog/4bit-transformers-bitsandbytes
[37] Improving LoRA: Implementing Weight-Decomposed Low-Rank Adaptation (DoRA) from Scratch: https://magazine.sebastianraschka.com/p/lora-and-dora-from-scratch
[38] Profiling your PyTorch Module: https://pytorch.org/tutorials/beginner/profiler.html
[39] PyTorch Profiler With TensorBoard: https://pytorch.org/tutorials/intermediate/tensorboard_profiler_tutorial.html
[40] Profiling to understand torch.compile performance: https://pytorch.org/docs/stable/torch.compiler_profiling_torch_compile.html
[41] TensorFlow Profiler: производительность модели профиля: https://www.tensorflow.org/tensorboard/tensorboard_profiling_keras?hl=ru
[42] Profiling Deep Learning Applications with NVIDIA NSight: https://www.youtube.com/watch?v=K27rLXkOiqo
[43] CUDA Developer Tools | Memory Analysis with NVIDIA Nsight Compute: https://www.youtube.com/watch?v=GCkdiHk6fUY
[44] Profiling with DLProf Pytorch Catalyst part 1: https://www.youtube.com/watch?v=Tf1U11C8B08
[45] на GitHub: https://github.com/mikeroyal/eBPF-Guide
[46] Документация: https://docs.rapids.ai/api/cudf/stable/
[47] Документация: https://docs.nvidia.com/deeplearning/dali/user-guide/docs/index.html
[48] Efficient Training on Multiple GPUs: https://huggingface.co/docs/transformers/perf_train_gpu_many
[49] Серия видео: https://www.youtube.com/playlist?list=PL_lsbAsL_o2CSuhUhJIiW0IkdT5C2wGWj
[50] Серия видео: https://www.youtube.com/playlist?list=PL_lsbAsL_o2BT6aerEKgIoufVD_fodnuT
[51] Dynamic Batching & Concurrent Model Execution: https://github.com/triton-inference-server/tutorials/blob/main/Conceptual_Guide/Part_2-improving_resource_utilization/README.md
[52] Источник: https://habr.com/ru/companies/selectel/articles/822651/?utm_source=habrahabr&utm_medium=rss&utm_campaign=822651
Нажмите здесь для печати.