16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час

в 11:33, , рубрики: Amazon EC2, Amazon Web Services, data mining, jupyter notebook, python, scikit-learn, виртуализация, хостинг

Если Вам не очень повезло, и на работе нет n-ядерного монстра, которого можно загрузить своими скриптами, то эта статья для Вас. Также если Вы привыкли запускать скрипты на всю ночь (и утром читать, что где-то забыли скобочку, и 6 часов вычислений пропали) — у Вас есть шанс наконец познакомиться с Amazon Web Services.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 1

В этой статье я расскажу, как начать работать с сервисом EC2. По сути это пошаговая инструкция по полуавтоматической аренде спотового инстанса AWS для работы с Jupyter-блокнотами и сборкой библиотек Anaconda. Будет полезно, например, тем, кто в соревнованиях Kaggle все еще пользуется своим игрушечным маком.

Наверное, реакция каждого, кто в первый раз зашел на сайт Amazon Web Services — это растерянность от обилия предлагаемых услуг и виртуальных машин (которые там называются инстансами).
В этом тьюториале я покажу, как недорого арендовать вычислительный инстанс AWS и быстро настроить на нем сервер Jupyter, чтоб пользоваться столь полюбившимися блокнотами. Акцент сделаем на сборке Anaconda и задачах машинного обучения, но понятно, что сервер можно в разных целях использовать, хоть биткоины майнить :)

Мотивация: хотим быстро (в течение 5-7 минут) получать доступ из Jupyter-блокнотов к вычислительным ресурсам посерьезней, чем у домашнего компа.
Вообще есть под это дело неплохой тьюториал. Статья, которую Вы читаете — вольный перевод с дополнениями. Мы еще напишем скрипт, который будет запускаться каждый раз при аренде машины. А вот и результат для тех, кто в спешке.

Арендовывать мы будем спотовый инстанс с3.4xlarge с 16 ядрами и 30 Гб RAM.
«Спотовый» означает, что по сути мы будем участвовать в аукционе и, назначив цену за час пользования машиной, иметь к ней доступ до тех пор, пока спрос не возрастет. Если спрос возрастет, и рыночная цена превысит ту, которую мы назначили, машина от нас «убежит», причем внезапно. Именно по этой причине (нестабильности) многие боятся пользоваться спотовыми инстансами, хотя на них можно сильно сэкономить по сравнению с инстансами «по требованию». Та же машина, но в более «стабильном» режиме, обойдется примерно в $0.85/час, мы же потратим вчетверо меньше.

Теперь про типы машин. Они неплохо описаны в документации AWS, так что выбираем тип С — машины, оптимизированные для вычислений.

Аренда машины

Для начала зарегистрируемся на сайте Amazon Web Services. Тут инструкций писать не буду — все как обычно, надо будет только подтвердить и по телефону, и по e-mail. К аккаунту надо будет кредитную карту привязать, но если боитесь трат, можно инстанс m4large (2 CPU, 8 Gb RAM) взять за $0.05/час.

Заходим в свою консоль AWS и находим в Services службу EC2 (Elastic Compute Cloud)

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 2

В разделе Spot Requests жмем «Request Spot Instance».

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 3

Выбираем тип ОС, которая будет стоять на виртуальной машине. В общих чертах: Windows дороже, среди *Nix не так важно, какую именно выбирать, пусть это будет Ubuntu.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 4

На следующей вкладке нам предлагают выбрать собственно инстанс. Здесь позалипаем, посравниваем (тут все подробней описано) и прокрутим до с3.4xlarge.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 5

Затем самое главное — назначить цену за час пользования виртуалкой. Мы видим текущие цены в выбранных регионах.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 6

Если видите, что у Вас цены намного выше, чем на скриншоте, значит, сейчас в текущем регионе всплеск — смените регион (в правом верхнем углу рядом с Вашим именем). Я пока с успехом использую регион Frankfurt, но можно и поизучать статистику, посмотреть, какие регионы подешевле и со стабильными ценами.

Цену лучше назначать раза в 1.5 выше текущей рыночной стоимости инстанса в данном регионе. При таком раскладе цена будет немного колебаться, но редко превышать заявленную Вами. Соответственно, так машина не часто будет «отваливаться».

Теперь подключим хранилище. Amazon угощает тридцатью Гб, так что почему бы не взять все 30…

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 7

Тегирование инстанса можно пропустить. И далее настройка портов. Тут главное — открыть порт, который мы будем использовать под Jupyter-сервер. Пусть по традиции это будет 8888. Жмем «Add rule», оставляем вариант «Custom TCP rule» и указываем порт 8888. Также добавляем протоколы HTTP и HTTPS и говорим, кто может прослушивать порты. Достаточно выбрать справа галки My IP.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 8

На следующем шаге создаем ключ (pem-файл), который будет нас идентифицировать при удаленном подключении к машине через SSH протокол. Можно его назвать как угодно — главное после скачивания знать, где он лежит и ни в коем случае (!!!) не выкладывать на GitHub или куда-то еще онлайн. Относитесь к этому файлику почти как к паролю от банковской карты. Amazon рекомендует периодически обновлять pem-файлы (их можно иметь по 2 в каждом регионе, второй раз скачать тот же самый ключ нельзя).

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 9

Наконец все подтверждаем, ждем пару минут, пока инстанс запустится, и в EC2 на вкладке «Instances» замечаем, что что-то появилось.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 10

Выбираем появившийся инстанс и жмем Connect. Amazon дает инструкции, что делать дальше.

Если Вы сидите под Windows, то для Вас чтение статьи не заканчивается (обычно на этом месте в тьюториалах можно прочитать «Windows? Good luck!»). Надо только прочитать инструкции Amazon, как подключиться с помощью Putty.
Если же Вы под *NIX, то выполняем указанные 2 команды:

chmod 400 <PEM-file name>.pem
ssh -i <PEM-file name>.pem ubuntu@<HOST>

Первая заботится о том, чтоб не у всякого проходящего был доступ к Вашему pem-файлу. Вторая — это собственно подключение к виртуалке cо своим уникальным хостом .

Настройка машины

Если все прошло гладко, вы как юзер ubuntu попадете в терминал удаленной машины.
Можем делать что угодно, запускать любые скрипты, но мы остановимся на настройке инстанса для задач машинного обучения с Jupyter. Все команды далее описаны, чтоб в них было проще разобраться (и убедиться, что все обошлось без шуточек в стиле rm -rf /), но вообще второй раз и далее мы это будем запускать bash-скриптом.

Скачиваем и устанавливаем Miniconda. Она все же намного легче Anaconda, а необходимые библиотеки мы доустановим (впрочем, seaborn у меня не попер, а с Anaconda все нормально). Мы с машинкой ненадолго, вряд ли больше чем на несколько часов, так что без перфекционизма — устанавливаем все в домашний каталог.

wget -c http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh
bash Miniconda-latest-Linux-x86_64.sh -b -p ~/miniconda
export PATH=~/miniconda/bin:$PATH

Теперь установим все библиотеки, какие захотим.

conda install -y numpy scipy pandas scikit-learn jupyter

Можно, например, и Vowpal Wabbit поставить (шустрые линейные модели, которые на больших выборках порой считаются и побыстрее MapReduce-реализаций).

sudo apt-get -qq install vowpal-wabbit

Не помешает и Git — так можно сразу нужный репозиторий скачать (использование Amazon S3 я в данном тюьториале не рассматриваю).

sudo apt-get -qq install git

Создадим сертификат, чтоб входить на Jupyter по паролю — так намного безопасней. Сейчас сделаем это руками, со второго раза этот созданный сертификат будет использоваться скриптом.

openssl req -x509 -nodes -days 365 rsa:2048 -keyout jupyter.pem -out jupyter.pem

Появится запрос об информации пользователя. В принципе это не обязательно заполнять.

Теперь создадим пароль для входа на Jupyter-сервер.
Можно воспользоваться функцией passwd из Ipython

python
>>> from IPython.lib import passwd
>>> passwd('Sample password')

Появится хэш Вашего пароля. Копируем его.

'sha1:d0c0b7eb515e:f0e59fcd04aec7bb50886084ae8e1fa9a273f88e'

Наконец, создаем профиль IPython и запускаем сервер, предварительно указав в файле настроек, какой порт мы хотим использовать и с каких адресов разрешен доступ. Указываем хэшированный пароль. У Вас пароль будет отличаться — надо вставить свой.

ipython profile create nbserver

printf "n# Configuration file for ipython-notebook.n
c = get_config()n
# Notebook confign
c.NotebookApp.ip = '*'n
c.NotebookApp.password = u''sha1:d0c0b7eb515e:f0e59fcd04aec7bb50886084ae8e1fa9a273f88e''n
c.NotebookApp.open_browser = Falsen
c.NotebookApp.port = 8888n" >> ~/.ipython/profile_nbserver/ipython_notebook_config.py

Последнее, что мы делаем только на удаленной машине — запускаем IPython-сервер.
(Почему IPython, а не Jupyter?.. Почему certfile явно указан? Ответ простой: костыли. Jupyter не хотел видеть config-файл, а потом не хотел в нем видеть настройки файла сертификата. Проверьте, может, у Вас и с командой jupyter запустится, и без явного указания файла настройки и сертификата).

ipython notebook --config="~/.ipython/profile_nbserver/ipython_notebook_config.py" --certfile=jupyter.pem

Если все прошло удачно, Вы увидите в конце прочитаете что-то типа этого.

[I 10:09:08.774 NotebookApp] Serving notebooks from local directory: /home/ubuntu
[I 10:09:08.775 NotebookApp] 0 active kernels 
[I 10:09:08.775 NotebookApp] The Jupyter Notebook is running at: https://[all ip addresses on your system]:8888/
[I 10:09:08.775 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

Профит

Теперь переходим в браузере на HOST:8888, где HOST — это, по-прежнему, адрес вашего инстанса. Внимание! Протокол должен быть именно HTTPS, может также понадобиться подтверждение сертификата. (Например, в Chrome надо ткнуть «Дополнительные» и подтвердить переход на сайт).

Вводим свой пароль (тут уже, само собой, не хэшированный, а «обычный») и видим приятную картинку — файловую систему из Jupyter.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 11

Создаем новый блокнот и радуемся обилию ядер под капотом.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 12

Теперь вернемся в терминал (нашего компа, а не удаленной машины) и закинем на наш инстанс какой-нибудь набор данных. Скажем, из соревнования Kaggle "Forest Cover Type Prediction".

scp -i <PEM-file name>.pem <LOCAL_PATH_TO_DATA> ubuntu@<HOST>:/~

Про машинное обучение, конечно, интересно поговорить, но тут мы просто запустим случайный лес Sklearn на сырых данных.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 13
Обратите внимание на параметр n_jobs — тут мы как раз и задействуем все 16 ядер.
1000 деревьев максимальной глубины 15 обучились ~ за 5 секунд — в 3 раза быстрее, чем на моем MacBook Air c 4 ядрами и 4 Гб памяти. На больших выборках разница, конечно, будет существенней.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 14

То же самое скриптом

Процесс можно автоматизировать. С помощью Python Amazon SDK по имени boto можно и резервирование спотового инстанса скриптом делать. Но пока мы посмотрим на скрипты, которые готовят машину для работы с Jupyter уже после того, как она запустилась.

Все это — в репозитории Github.

Всего понадобятся 3 файла:

  • В config.txt записываете путь к своему pem-файлу, хост свеже выданного инстанса, а также хэшированный пароль доступа к Jupyter-серверу, который мы создавали чуть раньше.
    pemfile='<PEM-file>.pem'
    host='<HOST>'
    jupyter_password='<JUPYTER_PASSWORD>'
    

  • В remote_setup.sh дописываете все, что хотите выполнить на удаленной машине.
    # Installing Miniconda
    wget -c http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh
    bash Miniconda-latest-Linux-x86_64.sh -b -p /home/ubuntu/miniconda
    export PATH=/home/ubuntu/miniconda/bin:$PATH
    
    #Installing neccesary libraries
    conda install -y numpy scipy pandas scikit-learn jupyter
    
    #Can add whatever you want to install
    #sudo apt-get -qq install vowpal-wabbit
    #sudo apt-get -qq install git
    
    ipython profile create nbserver
    
    printf "n# Configuration file for ipython-notebook.n
    c = get_config()n
    # Notebook confign
    c.NotebookApp.password = u'"$1"'n
    c.NotebookApp.ip = '*'n
    c.NotebookApp.open_browser = Falsen
    c.NotebookApp.port = 8888n" > ~/.ipython/profile_nbserver/ipython_notebook_config.py
    
    ipython notebook --config="~/.ipython/profile_nbserver/ipython_notebook_config.py" --certfile=jupyter.pem
    

  • Скрипт launch_remote_setup.sh просто выполняет remote_setup.sh с нужными параметрами на удаленной машине.
    source 'config.txt'
    
    scp -i $pemfile ./ipython.pem ubuntu@$remote_host:~
    
    ssh -i $pemfile ubuntu@$remote_host 'bash -s' < remote_setup.sh $jupyter_password
    

В нужном каталоге выполните:

sh launch_remote_setup.sh

5-7 минут, и все! Можно работать с Jupyter-сервером.

Уже собрался было налить чаю. Но! Очень важный момент!
По окончании работы остановите ваш инстанс.
EC2 -> Instances -> Actions -> Instance State -> Terminate.

Именно terminate, а не stop (хотя для спотовых это только и доступно). Но в случае запуска инстансов по требованию stop не полностью выключает машину, могут набегать деньги за обмен данными.

16 ядер и 30 Гб под капотом Вашего Jupyter за $0.25 в час - 15

Напоследок можно немного обсудить финансы. Текущий счет проверяется в Amazon при нажатии на свое имя и потом на «Billing & Cost Management».
$0.25 / час — это около $25 в месяц, если пользоваться по 4 часа каждый будний день. Дальше каждый сам решает, готов ли на такие траты.

Можно тут прорекламировать и GitHub Student Developer's Pack — я лично с их помощью получил сертификат Amazon на $110, все еще им пользуюсь. Кроме того, для серьезных научных проектов можно получить и грант Amazon.

Заключение

На этом пока все. Думаю, для некоторых это был jump-start в Amazon Web Services EC2. Дадим своим машинкам отдохнуть ночью!

PS. Замечания / советы / обмен опытом / pull request'ы приветствуются.

Автор: yorko

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js