Почему GPU обманывают о своей нагрузке и как с этим бороться |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2022-04-26 15:08 В предыдущем посте я рассказывал о том, как мы строили свои суперкомпьютеры. В этом — поделюсь опытом, который мы накопили, эксплуатируя наши кластеры. Этот опыт будет полезен не только тем, кто обучает огромные ML-модели. На грабли, о которых пойдёт речь, легко наступить, даже если вы специалист с парой GPU. Почему в распределённом обучении нельзя доверять утилизации GPU? Почему переход в эру распределённого обучения — фундаментальный сдвиг парадигмы мышления, к которому должен быть готов каждый ML-разработчик? Ещё больше «Почему» и ответов на них — под катом. Всё началось с жалобы моего коллеги MichaelEk: распределённое обучение моделей YaLM для Поиска, Алисы и других проектов иногда необъяснимо зависало. Мир машинного обучения сейчас движется по пути внедрения foundation-моделей, к которым относится и YaLM. Речь идёт о больших системах — каждая обучается один раз и требует огромных ресурсов, а дальше её можно довольно быстро дообучить под конкретное применение (например, для ранжирования ответов в поиске). Это примерно как научить делать конкретные задачи человека, уже способного читать и писать. Более подробно концепция описана у Григория Сапунова. В данном случае распределённое обучение — это когда GPU на разных узлах (хостах) c помощью библиотеки NCCL соединяются вместе и работают как единое целое, синхронно выполняя повторяющийся набор шагов, который выглядит примерно так:
На первый взгляд, ничего подозрительного не происходило. GPU и CPU заняты. Но глаз зацепился за то, что при стопроцентной утилизации GPU они совершенно холодные и не потребляют энергии.
Это выглядит очень странно — принцип Ландауэра ещё никто не отменял. Если нет потребления энергии, значит, и вычислений нет, а цифры утилизации — непонятный артефакт. Выяснилось, что треды на самом деле постоянно зовут yield() , и стек приложения выглядит так:
Синхронизация данных на шаге (4) происходит через busy_loop , который и даёт нам фейковую утилизацию GPU. Использование busy_loop в данном случае вполне оправдано, так как мы имеем дело со скоростями порядка 24 ГБ/с. Фейковая утилизация — побочный эффект того, что мы ждём завершения обмена данными от шага (3). Почему же данные по RDMA передаются настолько долго, что GPU успевают остыть после шага (2)? Причина оказалась комплексной, но очевидной.Слабые места InfiniBand-фабрики Для начала мы поймали:
Проблемные кабели нашли и заменили, наладили автоматическую починку. Самый важный индикатор ошибок InfiniBand — это счётчик symbol_errors, за ним обязательно должна следить автоматика. Но проблема не исчезла. На кластере всё равно оставались процессы, которые показывали фейковую утилизацию. Только выглядели они теперь чуть-чуть по-другому. FLP impossibility in action Второй класс проблем выглядел так: семь GPU показывали фейковую стопроцентную утилизацию, а восьмой — 0%.
Причина оказалась банальной: если один из процессов в распределённом обучении падал, то остальные этого не замечали и бесконечно ждали от него данных. Всё в соответствии с самой знаменитой теоремой распределённых алгоритмов — the FLP impossibility:
Чтобы алгоритм стал устойчивым к сбоям, нужно сделать его асинхронным не полностью, а частично. А именно — добавить таймаут на каждую операцию. Это знает каждый, кто занимается распределёнными алгоритмами. Авторам PyTorch это тоже известно, поэтому они добавили таймаут на групповые операции, но проблема в том, что он не включён по дефолту при использовании NCCL. В результате алгоритм висел, пока автор задачи не вспоминал, что запущенная операция почему-то до сих пор не завершилась. Мы выяснили что такие зависшие обучения занимали 2–3% наших кластеров (на наших объёмах это больше 1 PFLOPS) и стоили компании десятки тысяч долларов в месяц. Это поправили явным выставлением переменной NCCL_ASYNC_ERROR_HANDLING=1 для всех обучений.Важно: эта опция работает только для PyTorch. В других библиотеках детектирование зависаний может потребовать других опций, либо не иметь такой механики вовсе. В этом случае пользователю нужно самому детектировать зависание распределённого алгоритма. Самый простой способ проверить, умеет ли ваша библиотека или инфраструктура детектировать зависание, — явно спровоцировать его. Например, добавив sleep(3600) в случайное место алгоритма. Вот тест на зависание NCCL. Для наших кластеров мы реализуем детектирование зависающих обучений на уровне планировщика задач YT, о принципах его работы ниже. Закон Амдала наносит ответный удар После внедрения механики детектирования зависших обучений мы начали получать много ложнопозитивных сигналов от обучений, которые не зависли окончательно, а периодически замирали по непонятной причине. Разберём наглядный пример: обучение на восьми узлах (64 GPU) часто показывает стопроцентную утилизацию сразу на всех GPU, а потребление энергии остаётся на минимуме. Это явный признак проблем в обмене данными. Но уверенности в том, что это реальная проблема, нет. К этому времени глаз был уже намётан, и проблему удалось обнаружить быстро. Обучение выполняет 10 итераций, а потом создаёт снапшот накопленных данных на случай падения. Проблема в том что данные для этого снапшота передавались синхронно во внешнее хранилище по медленной сети и занимали 50% времени, а GPU всё это время простаивали. Классический кейс закона Амдала: последовательная операция ограничивает параллелизм. Почему же автор кода не заметил эту проблему при отладке? Ответ оказался простым: во время отладки код запускался на одном узле, а снапшот выполнялся на локальный NVME и происходил очень быстро. Но после того как код запущен в продакшн уже на восьми узлах, количество данных, которое нужно сохранять также вырастает в восемь раз. А снапшот сохраняется в надёжное геораспределённое внешнее хранилище, который оказался слишком медленным для таких нагрузок. После осознания проблемы решить её не составило труда. Сохранение снапшота сделали шардированным и асинхронным, после чего проблема исчезла. Методика построения кардиограмм распределённого обучения помогла нам обнаружить огромное количество неоптимальных мест. Даже когда мы внедрили ZeRo3, где вычисления и коммуникации происходят параллельно, подвисания, вызванные внешней коммуникацией, по-прежнему отлично видны. Нехватка CPU при работе с RDMA Четвёртый класс проблем, на которые мы наступили, был менее очевидным, и в чём-то более обидным. Почему распределённое обучение — это сложно? Прочитав предыдущие разделы, вы можете задать вопрос: а почему всё так сложно? Нельзя ли попроще? В этой части я объясню, почему в словосочетании «распределённое обучение» самое важное слово — «распределённое», и что распределённые алгоритмы — самая трудная область computer science. Совсем просто тут не бывает, но можно сильно упростить жизнь ML-разработчика, если дать ему удобную инфраструктуру.
Каждый из нас знает, что многопоточное программирование намного сложнее обычного линейного — этому учат в школах и университетах. Но почему-то не учат, что распределённые алгоритмы ещё гораздо сложнее. Возможно, потому, что раньше с распредёленными алгоритмами в реальной жизни сталкивался только узкий круг людей. Но за последние несколько лет распределённые алгоритмы стали обязательным атрибутом машинного обучения. Каждому ML-разработчику нужно обязательно держать в голове потенциальный круг проблем, с которым ему придётся столкнутся. Когда в работе распределённого алгоритма задействованы сотни узлов (хостов), тысячи сетевых карт и GPU, вероятность случайного отказа одного из этих компонентов становится более чем реальной. Если обучение длится несколько недель, как минимум один железный сбой точно случится. Нужно понимать, что произойдёт в этом случае. Как было показано выше, если не предпринимать никаких шагов, скорее всего распределённое обучение просто зависнет и тысячи GPU будут простаивать в бесконечном ожидании. Поэтому алгоритм распределённого обучения должен быть готов к сбоям. А именно:
Чтобы упростить реализацию надёжных алгоритмов, устойчивых к сбоям и зависаниям, мы сделали трёхступенчатую систему мониторинга на уровне планировщика YT:
Тестирование железа на шаге (1) — очень важный момент, потому что позволяет гарантировать пользователю исправность железа во время запуска пользовательского кода, потратив всего 10–100 секунд. Но ещё более важно повторно тестировать железо на шаге (4), потому что тестирование позволяет ответить на вопрос, почему задача упала. Если на шаге (4) мы нашли проблемы в железе, то всё понятно. Проблемный хост исключается из кластера и уходит на углублённую диагностику, пользовательская задача перезапускается без ручного вмешательства. Но если на шаге (4) проблем с железом не обнаружено, то, скорее всего, причина падения в самом коде задачи и перезапускаться не имеет смысла. Нужно отправить уведомление автору, чтобы он сам мог разобраться с проблемой. P. S. Я счастливый человек. Мне повезло в самом начале карьеры обжечься на сложности распределённых алгоритмов. На предыдущем месте работы мы коллективом очень неглупых людей потратили пару недель на изобретение механизма репликации в распределённой ФС, который противоречил теореме FLP. По факту изобретали вечный двигатель. В какой-то момент к нам пришёл Александр Тормасов, показал теорему и посоветовал просто добавить таймауты в алгоритм. После этого мы быстро решили задачу. С тех пор при упоминании слова «distributed» у меня сразу же включается режим повышенного внимания, чего и вам советую. Источник: habr.com Комментарии: |
|