Опыт разработки: почему мы пишем инфраструктуру машинного обучения на Go, а не на Python
Разработчик Cortex Калеб Кайзер делится соображениями о преимуществах применения Go для инфраструктурных решений в ML-проектах и о том, как два языка могут дополнять друг друга.
Python – самый популярный язык в машинном обучении. У Julia, R и C++ тоже есть поклонники в мире ML, но Python ушёл далеко вперёд. Cortex – open source платформа для развёртывания моделей машинного обучения. В нашем репозитории тоже есть место для Python, но на 87.5% код состоит из Go.
Алгоритмы, в которых блистает Python, являются лишь одним из компонентов систем коммерческого машинного обучения. Чтобы в реальности запустить API, нужна инфраструктура:
- Автоматическое масштабирование, чтобы колебания трафика не роняли API
- Менеджмент API для обработки одновременных развёртываний
- Роллинг-релизы, чтобы обновлять модели, продолжая обслуживать пользователей
Наряду с логированием и оптимизацией затрат Cortex создан для автоматизации инфраструктуры. Go идеально подходит для создания подобного программного обеспечения. Причины, по которым мы используем Go, вынесены в названия разделов публикации.
1. Конкурентность имеет решающее значение для инфраструктуры машинного обучения
У пользователя может быть много разных моделей, развёрнутых в виде отдельных API, управляемых в одном кластере. Чтобы оператор мог управлять различными развёртываниями, необходимо использовать несколько различных API. Например:
- API-интерфейсы Kubernetes, вызываемые для размещения моделей в кластере.
- Различные интерфейсы для API в AWS: EC2 Auto Scaling, S3, CloudWatch.
Пользователь не взаимодействует ни с одним из этих API напрямую. Вместо этого Cortex программно вызывает API, запускает развёртывание и мониторинг. Выполнить эффективно все пересекающиеся вызовы API – сложная задача. Конкурентное выполнение является наиболее эффективным способом решение подобных трудностей. Но конкурентность может добавить сложности, ведь нужно беспокоиться о таких вещах, как состояние гонки (англ. race condition).
Go предлагает элегантное решение – горутины. Если говорить упрощённо, горутины – это лёгкие потоки, автоматически управляемые средой выполнения Go. В одном потоке выполнения операционной системы умещается много горутин. А если горутина блокирует поток ОС, среда выполнения Go автоматически перемещает оставшуюся часть горутин в новый поток ОС.
Горутины поддерживают инструмент каналов. Каналы позволяют горутинам обмениваться сообщениями и синхронизируют их выполнение.
Этих возможности в Python можно реализовать с помощью сравнительно нового инструмента asyncio. Но язык Go исходно разрабатывался с ориентиром на высокую производительность, и эти инструменты плотнее интегрированы в язык.
2. В Go проще построить кроссплатформенный CLI
Cortex CLI – кроссплатформенный инструмент, с помощью которого пользователи могут размещать модели и управлять API-интерфейсами непосредственно из командной строки.
Первоначально мы писали CLI на Python, но попытка дистрибуции между различными платформами оказалась слишком сложной. Go компилируется в один двоичный файл. Управление зависимостями не требуется. Это простое решение для распространения CLI на других платформах без значительных инженерных усилий.
Также значительны преимущества в производительности скомпилированного двоичного файла Go по сравнению с интерпретируемым языком. Согласно бенчмаркам, Go значительно быстрее Python. Не случайно, что многие другие инструменты CLI для инфраструктуры написаны на Go, что подводит нас к следующему пункту.
3. Экосистема Go отлично подходит для инфраструктурных проектов
Одно из преимуществ open source – можно учиться на проектах, которыми вы восхищаетесь. Например, Cortex существует в экосистеме Kubernetes, которая сама написана на Go. Вот примеры замечательных проектов экосистемы, все с открытым исходным кодом на Go:
- kubectl: Kubernetes CLI
- minikube: Инструмент для локального запуска Kubernetes
- helm: Пакетный менеджер Kubernetes
- kops: Инструмент для управления продакшном Kubernetes
- eksctl: Официальный CLI для Amazon EKS
Если вы посмотрите на инфраструктурные проекты CockroachDB или Hashicorp, включая Vault, Nomad, Terraform, Consul и Packer, все они тоже написаны на Go.
Популярность Go в мире инфраструктур имеет и другой эффект. Большинство инженеров, заинтересованных в работе над инфраструктурными проектами, знакомы с этим языком. Один из лучших инженеров в Cortex Labs нашёл нас, ища вакансии Go.
4. Работать с Go приятно
Да, в сравнении с Python, с Go немного болезненнее начинать (прим. редактора: Библиотека программиста подготовила отдельную статью Go vs Python). Однако впоследствии от применения Go в крупных проектах получаешь радость. Две вещи, которые делают Go менее удобным для начинающих – статическая типизация и компиляция. Но они же служат защитными ограждениями, учат писать код с меньшим числом ошибок.
Наверняка и другие языки, о которых вы могли бы поспорить, дают опредёленное преимущество, но в итоге Go лучше всего отвечает нашим техническим и эстетическим требованиям.
Python – для машинного обучения, Go – для инфраструктуры
Мы любим Python. Он по-прежнему присутствует в Cortex, особенно в обработке вывода. Cortex обслуживает TensorFlow, PyTorch, scikit-learn и другие модули Python. Это означает, что взаимодействие с моделями, а также пред- и постобработка выполняются на Python. Однако даже этот код упакован в контейнеры Docker, которые организованы кодом на Go.
Если вы заинтересованы в том, чтобы стать инженером по машинному обучению, знание Python не подлежит обсуждению. Но если вы заинтересованы в работе над инфраструктурными решениями для машинного обучения, вам следует серьезно задуматься об использовании Go.
Что почитать дальше?
Если вас заинтересовал Go, команда Библиотека программиста подготовила обзор курса о программировании на Go (YouTube), собрала лучшие книги и ссылки. А ещё у нас есть специальный тег. Нужно что-то поправить, хотите узнать ещё – пишите в комментариях, мы отвечаем.