Одно из главных требований MXNet - это скорость! Особенно в распределенном режиме. Итак, я решил провести собственное расследование, чтобы ответить на вопрос: можно ли линейно масштабировать MXNet в распределенном режиме?

Отказ от ответственности

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

Кроме того, не ожидайте, что это будет научное исследование, поскольку все это было сделано с ограниченным бюджетом моего личного кошелька и, следовательно, не подтверждено достаточным количеством выполнений, чтобы сделать цифры статистически достоверными. Другими словами, результаты, полученные при однократном измерении без какой-либо информации об отклонении, среднем значении и других статистических данных, которые могут доказать, что результаты являются надежными. Хотя это похоже на то, что почти все делают в наши дни, и это меня огорчает :( В любом случае…

Настройка тестирования

  • AWS DeepLearning AMI (v 5.0) - на основе Ubuntu 16.04;
  • MXnet 1.1.0 (cu90mkl) - предварительно запеченный с AMI;
  • два p3.16xlarge (по 8 Вольт на каждом);
  • один p3.8xlarge (4 Вольта);

Единственная причина иметь третью машинку поменьше - моя ограниченность бюджета. Вольта стоит денег! В целом я старался не выходить за рамки бюджета в 50 долларов на свои исследования на выходных (и мне это удалось :)).

Что мы будем тестировать

MXNet предоставляет обучающий сценарий ImageNet, который можно запустить в тестовом режиме. "Вот этот". Мы собираемся запустить его следующим образом:

Как можно видеть:

Все в команде будет исправлено для всех выполнений, кроме трех вещей:

  • GPU, который мы будем использовать для обучения - в нашем примере их 8 штук;
  • Размер пакета для обучения - рассчитывается как 120 * количество графических процессоров; ** здесь нет никакого волшебства, это число просто рассчитывается на основе эмпирических наблюдений, которые позволяют нам максимально использовать RAM Volta.
  • KVstore - если вы не знаете, что такое KVStore, прочтите сначала другую мою статью.

База

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

Без лишних слов, вот измерение скорости от 1 до 8 вольт:

В идеальном мире с единорогами, пони и бабочками мы должны видеть такой линейный масштаб, даже если мы добавляем новые машины в кластер. Что-то вроде этого:

Есть несколько причин, по которым в реальной жизни такая масштабируемость невозможна (о чем мы поговорим позже), но мы все же можем проверить, насколько реальность близка к сказке, верно?

Распределенный режим обучения

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

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

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

Честно говоря, я был удивлен, когда увидел, насколько близка линия к базовой линии. Дело в том, что теперь у вас есть сеть. Да, все остается на локальном хосте, но, тем не менее, сеть задействована. К тому же, если мне не изменяет память, в 0.11 при такой настройке скорость падения составляла ~ 10%.

Просто сравните код, который выполняет Push на распределенном kvstore с аналогичным местом в local kvstore.

А теперь, думаю, пора по-настоящему испачкать руки. Мы собираемся начать первые распределенные эксперименты со следующей конфигурацией:

  • один сервер (размещенный вместе с воркером),
  • два рабочих,
  • kvstore в режиме синхронизации.

1 сервер 2 режима синхронизации рабочих

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

Когда вы впервые смотрите на диаграмму, может быть сложно понять ее смысл, но позвольте мне объяснить, что здесь происходит.

Все слева от черной середины вроде то же самое. Синий - это скорость тренировки на одном тренажере, а оранжевый - идеальная скорость тренировки. С правой стороны от черной линии у нас теперь есть данные от второго рабочего (поскольку единственный способ получить 9 вольт - это начать использовать второго рабочего). Как можно видеть, скорость первого рабочего сразу падает (до ~ 2400 с ~ 3000), когда мы добавляем вторую машину в кластер. Этому может быть несколько объяснений:

  • в первую очередь рабочий совместно размещает сервер, поэтому сервер может потреблять некоторый ресурс рабочего,
  • во-вторых, и это, вероятно, самое важное, мы используем режим синхронизации в нашем kvstore, поэтому теперь наш воркер будет блокироваться каждый раз, когда он пытается получить данные с сервера. Однако это не должно влиять на скорость трианирования (изображений / сек) и должно происходить только во время синхронизации с kvstore (но это еще предстоит определить).

Далее идет зеленая линия. Зеленая линия - скорость обучения второго рабочего. В идеале эта линия должна совпадать с синей линией слева. Однако этого не происходит. Например, при скорости 1 GPU на втором воркере это ~ 315 выборок / сек, а на первом - ~ 390–400. Это происходит, вероятно, по той же причине, что и падение скорости у первого рабочего.

Желтая линия показывает общую скорость кластера. Он равен сумме зеленой и синей линий. Как можно видеть, вам нужно 2 Вольта на втором рабочем, просто чтобы получить ту же скорость, что и на одной машине. Только после добавления третьего графического процессора (всего 11 графических процессоров) скорость выше, чем с 8 графическими процессорами!

Давайте относиться к нему как к нашей базовой линии и давайте попробуем превзойти его! Теперь я попробую другую конфигурацию.

2 сервера 2 режима синхронизации рабочих

В этой конфигурации у нас будет 2 сервера. На каждом сервере будет размещаться половина модели, поэтому теперь у каждого рабочего должна быть ~ равная скорость вытягивания / выталкивания модели. Наши текущие результаты следующие:

Эти результаты настолько невероятно красивы, что мне пришлось проводить измерения дважды! MXNet показывает почти идеальные результаты линейного масштабирования до 14 графических процессоров!

Первый рабочий практически не показывает снижения скорости, задействовано до 15 графических процессоров. Трудно сказать почему. Думаю, количество сетевых коммуникаций имеет значение. Поскольку теперь каждый сервер отвечает только за половину модели, рабочий, размещенный вместе с сервером, способен мгновенно обновлять половину модели. Во всяком случае, почему это происходит, ответить сложно. Теперь вопрос: можем ли мы сделать его еще лучше, используя асинхронный режим? Давайте попробуем:

2 сервера 2 рабочих в асинхронном режиме

И единственное отличие следующего символа, которое мне удалось найти, - это слово «async» в заголовке:

Итак, sync / async действительно не влияет на скорость обучения (хотя, вероятно, имеет некоторое влияние на время синхронизации модели). А что, если мы введем третьего рабочего? Учитывая всю текущую информацию, я думаю, не должно быть ничего удивительного в том, что мы собираемся использовать и третий сервер.

3 сервера 3 рабочих асинхронного режима

Теперь становится интересно:

Как видно, возникает узкое место. Хотя он все же намного лучше того, что мы видели в режиме одного сервера. Например, нет случаев, когда вам нужно добавить графический процессор только для достижения предыдущей скорости, в текущей конфигурации скорость всегда увеличивается с каждым последующим графическим процессором. На удивление скорость немного повышается с 20 Вольтами (на первых 2 рабочих).

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

Заключение

MXNet демонстрирует большой потенциал масштабирования почти линейно. Если вы планируете построить кластер, количество серверов является ключевой переменной и выглядит так, как будто у вас должен быть 1 сервер на 1 рабочего.

Что еще предстоит решить

Есть несколько вещей, которые мне бы очень хотелось увидеть:

  • Поддержка fp16 для распределенного обучения 0_0 IMHO это критический блокировщик удвоения скорости в распределенном режиме, я создал запрос функции, пожалуйста, не стесняйтесь +1 к нему,
  • возможность использования NCCL с распределенным обучением (запрос функции здесь).

Другие статьи серии «Подробное объяснение распределенного обучения MXNet»

Обновлено 4 марта 2018 г.