Майкл И. Джордан,профессор Калифорнийского университета в Беркли, и его исследовательская группа в лаборатории RISE разработали новую распределенную среду машинного обучения под названием Ray, которая поддерживает построение в реальном времени. системы обучения с подкреплением. Ray — это программная замена Spark, использующаямодель вычисления динамического графа задач, которая поддерживает как модели параллельного выполнения задач, так и модели программирования акторов. Там можно найти прекрасное вступление М. Джордана к Ray.



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

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

Архитектура Рэя

Архитектура Ray состоит из двух частей: уровня приложения и уровня системы.

Прикладной уровень состоит из трех компонентов. Это Водитель, Рабочий и Актёр.

Драйвер – это процесс, выполняющий пользовательскую программу.

Рабочий процесс — это процесс без сохранения состояния, который выполняет задачи (удаленные функции), вызываемые драйвером или другим рабочим процессом. Рабочие процессы запускаются автоматически, и им назначаются задачи системным уровнем. При объявлении удаленной функции она автоматически публикуется для всех рабочих процессов. Рабочий выполняет задачи последовательно.

Актор — это процесс с состоянием, который при вызове выполняет предоставляемые им методы. В отличие от рабочего процесса, актор явно создается рабочим процессом или драйвером. Подобно рабочим процессам, акторы последовательно выполняют методы.

Системный уровень состоит из трех основных компонентов: хранилища глобальных элементов управления, распределенного планировщика и хранилища распределенных объектов.

В Global Control Store (GCS) хранятся все актуальные метаданные и информация о состоянии элементов управления в системе. Он включает в себя 1) спецификацию каждой задачи, (2) код для каждой удаленной функции, (3) график вычислений, (4) текущее местоположение всех объектов и (5) каждое запланированное событие. GCS также предоставляет инфраструктуру публикации-подписки для облегчения связи между компонентами.

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

Распределенный планировщик "снизу вверх"

Рэй использует глобальный планировщик и локальные планировщики для каждого узла. Задачи, созданные на узле, сначала отправляются в локальный планировщик узла, а не в глобальный планировщик. Если локальный планировщик не планирует задачу, он отправляет задачу глобальному планировщику.

Каждый локальный планировщик отправляет периодические контрольные сообщения (например, каждые 100 мс) в GCS, содержащие информацию о его нагрузке. GCS записывает эту информацию и передает ее глобальному планировщику. При получении задачи глобальный планировщик использует самую последнюю информацию о нагрузке от каждого узла, а также расположение и размеры входных данных задачи (из метаданных объекта GCS), чтобы решить, какому узлу назначить задачу.

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

Хранилище распределенных объектов в памяти

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

Если входные данные задачи не являются локальными, входные данные реплицируются в локальное хранилище объектов на том же узле перед выполнением. Задачи также записывают все выходные данные в локальное хранилище объектов. Репликация устраняет потенциальные узкие места из-за горячих объектов данных и минимизирует время выполнения задачи, поскольку задача считывает и записывает данные только в локальную память. Это увеличивает пропускную способность для рабочих нагрузок, связанных с вычислениями, профиль, общий для многих приложений ИИ.

Сквозной пример, который добавляет a и b и возвращает c. Сплошные линии — это операции плоскости данных, а пунктирные линии — операции плоскости управления. (a) Функция add() регистрируется в GCS узлом 1 (N1), вызывается на N1 и выполняется на N >2. (b) N1 получает результат add() с помощью ray.get(). Запись таблицы объектов для c создается на шаге 4 и обновляется на шаге 6 после того, как c копируется в N1.

Функции Ray API

Основные четыре API

  1. список фьючерсов= f.remote(аргументы)

— Удаленное выполнение функции f(). f() принимает в качестве аргументов значения объекта или фьючерсы и возвращает список фьючерсов. Это неблокирующий вызов.

2. список объектов= ray.get(список фьючерсов)

— Возвращает значения, связанные со списком фьючерсов. Это блокирующий звонок.

3. список фьючерсов выполнен= ray.wait(список фьючерсов,k,время ожидания)

— Имея список фьючерсов, вернуть фьючерсы, соответствующие задачи которых завершены, как только завершится k задач или истечет время ожидания.

4. actor= Class.remote(args)
список фьючерсов= actor.method.remote(аргументы)

— Создать экземпляр класса Class в качестве удаленного субъекта и вернуть ссылку на него. Вызовите метод удаленного субъекта и верните список фьючерсов. Это неблокирующий вызов.

Вся информация взята из оригинальной статьи Ray: A Distributed Framework for Emerging AI Applications. Бумага ссылка. Репозиторий Ray на GitHub — https://github.com/ray-project.