尝试使用Spark × Keras × Docker对深度学习进行可扩展的尝试2:多节点版本

通过 Spark × Keras × Docker 尝试实现可扩展的深度学习2。

我以前尝试将Dist-keras放入Docker中,以创建可扩展的深度学习模型。
您可以在此链接中了解更多信息:http://qiita.com/cvusk/items/3e6c3bade8c0e1c0d9bf

当时的反省点是表现不佳,仔细回顾后发现参数设置错了。
于是为了反省而尝试了很多不同的方法。

之前的故事梗概

请参考先前的帖子获取关于Dist-Keras本身的解释,基本上它是在Spark集群上运行的Keras。
我将其制作成了Docker映像,以便可以轻松地扩展。

另外,Dockerfile已在GitHub上公开。
https://github.com/shibuiwilliam/distkeras-docker

我要做的事情

我想在本次测试中,使用Docker上的Dist-Keras在单主机和多主机上进行验证,以改善性能。
之前,我在单主机上启动了多个容器,创建了Spark集群。
这次,我想增加一些模式。

我们将运行的是MNIST。
MNIST的训练程序是基于dist-keras提供的进行自定义使用。

验证过的结构 le de

我们将使用单主机和多主机进行验证。
无论是单主机还是多主机,都是以Spark主节点+工作节点的配置,并调整工作节点的数量和规格。
在多主机的情况下,有两台服务器。
值得注意的是,主机是使用AWS EC2 CentOS7.3的m4.xlarge。

nohostsworkersresources1single11 processor, 2GB RAM2single22 processors, 5GB RAM3single31 processor, 3GB RAM4multihost22 processors, 5GB RAM5multihost23 processors, 8GB RAM6multihost42 processors, 5GB RAM

单个主机的设置方法

在单一主机的情况下,图像会是这样的。
Docker容器的数量会根据验证条件做出调整。

14.jpg

在单一主机上启动多个Docker容器,这是当只有一个主机时的情况。

# docker dist-keras for spark master and slave
docker run -it -p 18080:8080 -p 17077:7077 -p 18888:8888 -p 18081:8081 -p 14040:4040 -p 17001:7001 -p 17002:7002 \
 -p 17003:7003 -p 17004:7004 -p 17005:7005 -p 17006:7006 --name spmaster -h spmaster distkeras /bin/bash

# docker dist-keras for spark slave1
docker run -it --link spmaster:master -p 28080:8080 -p 27077:7077 -p 28888:8888 -p 28081:8081 -p 24040:4040 -p 27001:7001 \
-p 27002:7002 -p 27003:7003 -p 27004:7004 -p 27005:7005 -p 27006:7006 --name spslave1 -h spslave1 distkeras /bin/bash

# docker dist-keras for spark slave2
docker run -it --link spmaster:master -p 38080:8080 -p 37077:7077 -p 38888:8888 -p 38081:8081 -p 34040:4040 -p 37001:7001 \
-p 37002:7002 -p 37003:7003 -p 37004:7004 -p 37005:7005 -p 37006:7006 --name spslave2 -h spslave2 distkeras /bin/bash


使用Spark Master来启动Spark主节点和工作节点,而Spark Slave仅用于启动工作节点。

# for spark master
${SPARK_HOME}/sbin/start-master.sh

# for spark worker
${SPARK_HOME}/sbin/start-slave.sh -c 1 -m 3G spark://spmaster:${SPARK_MASTER_PORT}

接下来,我们将在Spark的主节点上对MNIST程序进行定制。
MNIST的示例代码是使用Dist-Keras提供的。
代码存放在目录/opt/dist-keras/examples中,那里包含以下的示例数据和程序。

[root@spm examples]# tree
.
|-- cifar-10-preprocessing.ipynb
|-- data
|   |-- atlas_higgs.csv
|   |-- mnist.csv
|   |-- mnist.zip
|   |-- mnist_test.csv
|   `-- mnist_train.csv
|-- example_0_data_preprocessing.ipynb
|-- example_1_analysis.ipynb
|-- kafka_producer.py
|-- kafka_spark_high_throughput_ml_pipeline.ipynb
|-- mnist.ipynb
|-- mnist.py
|-- mnist_analysis.ipynb
|-- mnist_preprocessing.ipynb
|-- spark-warehouse
`-- workflow.ipynb

复制原始文件以备份,然后应用以下更改。

cp mnist.py mnist.py.bk

修改项1:导入SparkSession。

我会把以下内容添加到开头。

from pyspark.sql import SparkSession

修改部分2:参数设置

将Spark参数根据本次环境进行更改。
更改的意图如下:
– 使用Spark2
– 使用本地环境
– 在本地环境中定义主节点url
– 根据验证条件更改处理器数量
– 根据验证条件更改工作节点数量

# Modify these variables according to your needs.
application_name = "Distributed Keras MNIST"
using_spark_2 = True  # False to True
local = True  # False to True
path_train = "data/mnist_train.csv"
path_test = "data/mnist_test.csv"
if local:
    # Tell master to use local resources.
#     master = "local[*]"   comment out
    master = "spark://spm:7077"  # add
    num_processes = 1 # change to number of processors per worker
    num_executors = 3  # change to number of workers
else:
    # Tell master to use YARN.
    master = "yarn-client"
    num_executors = 20
    num_processes = 1
变更项3:工人的内存

根据验证条件,调整工人的内存。

conf = SparkConf()
conf.set("spark.app.name", application_name)
conf.set("spark.master", master)
conf.set("spark.executor.cores", `num_processes`)
conf.set("spark.executor.instances", `num_executors`)
conf.set("spark.executor.memory", "4g") # change RAM size
conf.set("spark.locality.wait", "0")
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");

在Spark主节点上,您可以使用python mnist.py来运行。

多个主机的配置方法

多主机配置如下。

23.jpg

在多主机环境中,需要使用overlay网络来连接Docker容器。
有关在多主机环境下构建Docker网络的详细步骤,请查阅以下链接:
http://knowledge.sakura.ad.jp/knowledge/4786/

在这里,我只会写出我的步骤。
在EC2上准备host1和host2,安装etcd并在host1上启动。

yum -y install etcd

vi /etc/etcd/etcd.conf
systemctl enable etcd
systemctl start etcd

接下来,我们将在host1和host2上都添加Docker网络的配置。

# edit docker-network file
vi /etc/sysconfig/docker-network

# for host1
DOCKER_NETWORK_OPTIONS='--cluster-store=etcd://<host1>:2379 --cluster-advertise=<host1>:2376'

# for host2
DOCKER_NETWORK_OPTIONS='--cluster-store=etcd://<host1>:2379 --cluster-advertise=<host2>:2376'

# from host2 to ensure network connection to host1 etcd is available
curl -L http://<host1>:2379/version
{"etcdserver":"3.1.3","etcdcluster":"3.1.0"}

这将使得Docker之间的网络连接成为可能,然后只需在host1上创建Docker网络。
在这里,我们将使用子网10.0.1.0/24创建名为test1的Docker网络。


# for host1
docker network create --subnet=10.0.1.0/24 -d overlay test1

如果在最后运行docker network ls命令时,出现了test1网络,则表示OK。


NETWORK ID          NAME                DRIVER              SCOPE
feb90a5a5901        bridge              bridge              local
de3c98c59ba6        docker_gwbridge     bridge              local
d7bd500d1822        host                host                local
d09ac0b6fed4        none                null                local
9d4c66170ea0        test1               overlay             global

接下来将向test1网络中添加Docker容器。
我们将尝试在host1和host2上部署Docker容器。

# for host1 as spark master
docker run -it --net=test1 --ip=10.0.1.10 -p 18080:8080 -p 17077:7077 -p 18888:8888 -p 18081:8081 -p 14040:4040 -p 17001:7001 -p 17002:7002 \
-p 17003:7003 -p 17004:7004 -p 17005:7005 -p 17006:7006 --name spm -h spm distkeras /bin/bash

# for host2 as spark slave
docker run -it --net=test1 --ip=10.0.1.20 --link=spm:master -p 28080:8080 -p 27077:7077 -p 28888:8888 -p 28081:8081 -p 24040:4040 -p 27001:7001 \
-p 27002:7002 -p 27003:7003 -p 27004:7004 -p 27005:7005 -p 27006:7006 --name sps1 -h sps1 distkeras /bin/bash

现在在test1网络中成功部署了两个Docker容器,可以使用多主机。
接下来,按照单主机的步骤启动Spark Master和Spark Worker,并编辑MNIST.py文件,然后执行python mnist.py。

性能验证结果

这个实验是为了验证每种构成的性能而进行的。我们这次测量的是完成所需的时间(秒数)。

no.hostsworkersresourcestime in second1single11 processor, 2GB RAM1615.637572single22 processors, 5GB RAM1418.569353single31 processor, 3GB RAM1475.842124multihost22 processors, 5GB RAM805.3825185multihost23 processors, 8GB RAM734.2903246multihost42 processors, 5GB RAM723.878466

多重主机设置可以提高性能。我认为这是因为可用资源的数量产生了性能差异。
尽管验证2和验证4的Docker容器配置和工作资源使用相同,但仍然存在600秒的差距。
无论是比较验证1和验证2,还是验证4和验证5,验证6,Spark工作者数量和资源数量本身似乎并不产生重大的性能差异。
如果想要显著改善性能,最好选择多重主机设置。

【2017/05/26 附言】
我们使用Kubernetes构建了一个集群。
http://qiita.com/cvusk/items/42a5ffd4e3228963234d

广告
将在 10 秒后关闭
bannerAds