Не помещайте свои модели машинного обучения в AWS EBS
(при запуске из снапшотов)
Вот что я хочу. Мне нужен AMI, который я могу запускать в инстансе Amazon EC2 (с графическим процессором), чтобы запускать модель каждое утро вторника. Экземпляр должен загрузить модель, выполнить работу и затем умереть. Я хочу, чтобы все выполнялось как можно быстрее, и я хочу быть на 100% уверен, что изображение умрет, чтобы избежать больших счетов AWS.
В этой статье предлагается один из способов реализации вышеизложенного. Я также обсуждаю сделанную мной ошибку, а именно, сохранил мою модель машинного обучения в EBS, и что мне делать вместо этого.
Если вы просто хотите знать, почему НЕ EBS, перейдите ко второму разделу статьи и игнорируйте код.
Шаговые функции + Лямбда + EC2
Идея состоит в том, чтобы создать рабочий процесс пошаговой функции, который будет запускаться событием вторник Cloudwatch. Рабочий процесс будет последовательно выполнять следующие действия:
- Запустите Lambda, который запустит экземпляр EC2; Лямбда возвращает идентификатор экземпляра, который был запущен
- Следите за активностью инстанса EC2; программа, работающая внутри нашего экземпляра, должна запустить действие, отправлять тактовые импульсы каждую минуту, а затем сообщать об успешном выполнении задачи.
- Запустите ту же Lambda, которая завершит работу экземпляра EC2, используя предоставленный идентификатор экземпляра.
Вот спецификация языка Amazon States для этого рабочего процесса.
Нет, мы передаем идентификатор AMI и действие «start» в функцию Lambda, чтобы запустить экземпляр, и идентификатор AMI, действие «stop» и сгенерированный идентификатор экземпляра для остановки экземпляра. Наша лямбда-функция должна читать строку «действие» и запускать или завершать экземпляр.
Почему EBS не подходит для моделей машинного обучения?
Моя модель ML была около 5 ГБ. Не такая уж большая модель, но эй, я не OpenAI, и они (OpenAI) меня даже не любят (все еще ждут доступа к GPT-3).
Моя первоначальная идея - упаковать модель внутри AMI. Я не ожидаю частых обновлений модели, и я решил, что иметь все внутри корневого тома экземпляра будет достаточно быстро. В конце концов, какая настройка будет эффективнее, чем запуск сервера со всеми необходимыми файлами на диске ОС!
Я был неправ.
Загрузка модели 5 ГБ на мой настольный сервер занимает около двух минут. Та же модель заняла 20–30 минут для загрузки из EBS. Все это время графический процессор в основном спит, ожидая завершения ввода-вывода - пустая трата времени и денег.
Пожалуй, самое удивительное, что в этом нет ничего удивительного!
AWS предупреждает о сценариях, в которых образы EBS загружаются из моментальных снимков:
Для томов, созданных из моментальных снимков, блоки хранилища должны быть извлечены из Amazon S3 и записаны в том, прежде чем вы сможете получить к ним доступ. Это предварительное действие требует времени и может вызвать значительное увеличение задержки операций ввода-вывода при первом обращении к каждому блоку.
Облом! Исходя из вышеизложенного, нашей программе придется ждать, пока модель будет скопирована из S3 в EBS, каждый раз, когда мы запускаем новый экземпляр из AMI. Хотя S3 может быть быстрым, процесс синхронизации, реализованный AWS, довольно медленный.
Идеи?
Вот один.
Тома EBS - это сетевые диски. Они медленные и не предназначены для большого количества операций ввода-вывода. Для большего количества операций ввода-вывода вам понадобятся SSD-накопители с прямым подключением (без сети).
И угадай что. Экземпляры GPU поставляются с SSD-дисками, подключенными в качестве временного хранилища. Например, экземпляр g4dn.xlarge поставляется с твердотельным накопителем NVMe емкостью 125 ГБ, доступным на устройстве “/dev/nvme0n1”
. Woohoo!
Загвоздка в том, что эфемерное хранилище NVMe, в общем, эфемерное. Это означает, что если вы остановите или переведете экземпляр в спящий режим, данные будут потеряны. Поскольку мы запускаем экземпляр только один раз, а затем завершаем его, на нас это не сильно влияет. Однако при запуске инстанса временное хранилище будет пустым; следовательно, нам нужно скопировать модель в эфемерное хранилище откуда-то еще.
Очевидный выбор - S3. Это также дает нам возможность обновлять модель, не касаясь экземпляра. Все, что нам нужно сделать, это добавить дополнительную логику для копирования модели из S3 в локальный каталог, где смонтировано временное хранилище.
Как насчет стоимости трансфера? Если ваша корзина S3 и экземпляр находятся в одном регионе, вы платите 0,02 доллара США за каждый скопированный ГБ. Для 5 ГБ это 10 центов, что на 50% дешевле, чем 20 минут самого дешевого экземпляра g4dn.
Это может показаться нелогичным. Почему копировать данные при каждом запуске быстрее и дешевле, чем запускать с данными уже в образе? Собственно, так и должно быть. Большая часть содержимого томов EBS (файлы и библиотеки ОС) никогда не читается, и поэтому нет необходимости в большом количестве операций ввода-вывода. При необходимости следует использовать временное хранилище.
Приступаем к работе
Я сказал, что временный диск подключен к “/dev/nvme0n1”
(согласно панели инструментов AWS), но я обнаружил, что это не так в экземпляре Ubuntu Machine Learning Base AMI.
В моем случае эфемерное хранилище было подключено к “/dev/nvme1n1”
, и его нужно было разделить и смонтировать. Мое решение состояло в том, чтобы добавить сценарий, который разбивает и монтирует временное хранилище во время загрузки.
sudo nano /etc/rc.local mkfs -t xfs /dev/nvme1n1 /dev/nvme1n1 ~/<YOUR ML MODEL DIRECTORY> sudo chmod a+x /etc/rc.local
Если вы запускаете свою программу в контейнере докера, вам также необходимо смонтировать указанный выше каталог в докере, используя флаг -v
:
sudo docker run -ti — gpus all -v ~/<YOUR ML MODEL DIRECTORY>:/app/<YOUR ML MODEL DIRECTORY> — name [NAME] [IMAGE]
Уроки выучены
То, что «очевидно» должно работать, не всегда работает, но из этого может получиться хорошая статья.