Horovod 容器生存指南
作者: 胡瑛皓 (hyinghao@hotmail.com) 如轉(zhuǎn)載請聯(lián)系作者
Horovod 是Uber的一個開源深度學(xué)習(xí)工具,采用allreduce方法,為用戶提供分布式深度神經(jīng)網(wǎng)絡(luò)訓(xùn)練的解決方案。目前支持的深度學(xué)習(xí)框架包括: keras, pytorch和tensorflow。通過這套框架,用戶可以快速的將自己原有的代碼切換成分布訓(xùn)練模式,實現(xiàn)水平擴展(scale-out)大幅提升訓(xùn)練速度。撰寫本文目的是提供部署的經(jīng)驗,幫助用戶更快的從理論進入實戰(zhàn)部分。
編排結(jié)構(gòu)
這里采用的技術(shù)架構(gòu)是以docker作為深度訓(xùn)練的容器 ( 其中搭載 tensorflow, horovod 等軟件包 ) ,以rancher (v1.*) 作為可視化編排管理工具對容器進行水平擴展(注: 這里不會對rancher, docker private repository, docker等容器技術(shù)作過多闡述和說明。用戶可以采用其他容器技術(shù)或編排軟件自行配置),其編排結(jié)構(gòu)如下圖所示:
編排的所有操作均在rancher中部署,其中私有repo中保存配置好的horovod鏡像, 通過horovod-node服務(wù)進行水平擴展(service)。
容器安裝
horovod-node容器需容納tensorflow, horovod等運行環(huán)境,本文介紹基于ubuntu+python3的容器安裝步驟,需要依次進行:系統(tǒng)包安裝, python3包安裝, openmpi及horovod安裝
1. 操作系統(tǒng)包,wget, curl, vim, telnet, git,python3-pip, python3-dev, openssh-server 等基礎(chǔ)包請根據(jù)需要自行安裝。需要注意的是: horovod中使用 openmpi 作跨節(jié)點調(diào)用,其實質(zhì)是采用ssh執(zhí)行各種應(yīng)用程序并匯總結(jié)果。因此需要安裝openssh-server服務(wù),為其設(shè)定登錄密碼,同時暴露22端口,可參考 鏈接1 鏈接2。
RUN apt-get update && \
apt-get install -y openssh-server openssh-client
RUN mkdir /var/run/sshd
RUN echo 'root:password' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
另外,由于horovod的python包采用make install的方式安裝,需安裝以編譯開發(fā)環(huán)境 build-essential, gcc, g++, automake, make等;
2. 安裝python3包,安裝numpy, tensorflow, keras, pytorch, torchvision及相關(guān)依賴包;
3. openmpi/horovod 安裝,根據(jù)horovod官網(wǎng)上的說明進行下載安裝 。注意,openmpi安裝后需執(zhí)行l(wèi)dconfig命令對LD_LIBRARY_PATH變量進行配置。openmpi安裝后,便可直接安裝horovod的python包;
RUN wget https://download.open-mpi.org/release/open-mpi/v3.1/openmpi-3.1.2.tar.gz
ENV LD_LIBRARY_PATH "/usr/local/lib"
RUN tar -xzvf openmpi-3.1.2.tar.gz
WORKDIR /root/openmpi-3.1.2/
RUN ./configure --prefix=/usr/local && \
make all install
RUN ldconfig
WORKDIR /root/
4. 容器入口點改造。一般容器啟動點為一個單獨python/java程序,由于希望horovod-node以長服務(wù)形式出現(xiàn),將其改造為啟動ssh服務(wù),并不斷sleep等待。設(shè)定完畢,就可以為后續(xù)提供持續(xù)的算力服務(wù)。
sleep 5 && service ssh start
while true; do
sleep 5
done
代碼調(diào)整
我們以horovod官方自帶的(tensorflow_mnist.py)為例作為分布式訓(xùn)練的代碼。github上的代碼可以拿來直接使用,如稍作調(diào)整效果更好。
1. 數(shù)據(jù)集改造,代碼中對于每個節(jié)點均采用不同的數(shù)據(jù)集文件(根據(jù)hvd.rank()確定id),保證每個數(shù)據(jù)集可并發(fā)執(zhí)行,不會互相干擾。不過這種設(shè)計方式造成,這些文件會反復(fù)下載導(dǎo)致系統(tǒng)卡死,而且在國內(nèi)無法下載到谷歌提供的數(shù)據(jù)文件。在容器環(huán)境下為提高速度,建議將這些數(shù)據(jù)文件提前下載(數(shù)據(jù)集地址),解壓保存到rancher實例不同服務(wù)器下的同一個目錄下MNIST-data里,并修改70行:
# mnist = learn.datasets.mnist.read_data_sets('MNIST-data-%d' % hvd.rank())
mnist=learn.datasets.mnist.read_data_sets('MNIST-data')
2. epoch調(diào)整,如需要調(diào)整訓(xùn)練的epoch數(shù),可調(diào)整StopAtStepHook的last_step參數(shù)。
tf.train.StopAtStepHook(last_step=1000 // hvd.size()),
服務(wù)部署
把構(gòu)建好的容器,簡單封裝后部署到rancher,成為長服務(wù)方便后續(xù)使用。參考步驟如下:
1. 發(fā)布容器鏡像,tag容器鏡像并push到私有repo,發(fā)布至 rc01:5000/horovod:latest ;
2. 配置rancher服務(wù),編輯docker-compose.yml文件將容器部署為horovod-grid/horovod-node服務(wù)。映射數(shù)據(jù)集、代碼到容器/shared目錄,配置privileged: true模式:
version: '2'
services:
horovod-node:
image: rc01:5000/horovod:latest
restart: always
privileged: true
volumes:
- /data/shared:/shared
environment:
- LD_LIBRARY_PATH=/usr/local/lib
3. 在rancher服務(wù)中scale需要執(zhí)行的容器數(shù)量,本例圖中部署后得到2個節(jié)點的算力(10.42.239.218 和 10.42.201.106),分別位于2臺主機上,實際可根據(jù)具體需求部署算力:

4. 免密碼登錄
選擇任意一實例作為后續(xù)openmpi執(zhí)行的主節(jié)點(例如10.42.239.218), 在該實例上執(zhí)行,保證對于實例本身以及其他實例可以免密碼操作(做法與hadoop安裝過程中,免密碼登錄方式類似)。
# 為本機建立rsa秘鑰
ssh-keygen -t rsa
# 設(shè)置節(jié)點1
ssh root@10.42.239.218 mkdir -p /root/.ssh
cat /root/.ssh/id_rsa.pub | ssh root@10.42.239.218 'cat >> /root/.ssh/authorized_keys'
# 設(shè)置節(jié)點2
ssh root@10.42.201.106 mkdir -p /root/.ssh
cat /root/.ssh/id_rsa.pub | ssh root@10.42.201.106 'cat >> /root/.ssh/authorized_keys'
命令行啟動
遠程登錄部署好的主實例節(jié)點10.42.239.218, 執(zhí)行以下命令開始訓(xùn)練 (mpirun 參數(shù)說明 -np 進程數(shù)量, -H 主機列表, --allow-run-as-root 以root方式運行, -x 環(huán)境變量, -wd 工作目錄)
mpirun -np 2 \
--allow-run-as-root \
-H 10.42.239.218:1,10.42.201.106:1 \
-x LD_LIBRARY_PATH=/usr/local/lib \
-x PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games \
-wd /shared \
/usr/bin/python3.6 -u /shared/tensorflow_mnist.py
好了,到這里分布式訓(xùn)練系統(tǒng)就建設(shè)完成了,基于Horovod的應(yīng)用可生存在rancher中了 。每個容器實例消耗1個CPU的算力,因此可根據(jù)實際情況分布到不同主機host中進行計算。
如需要GPU配置,需在容器配置過程中安裝CUDA及相應(yīng)GPU版本,可參考官方版本docker文件。