Auparavant, je mettais Dist-keras sur Docker pour créer un apprentissage en profondeur évolutif. http://qiita.com/cvusk/items/3e6c3bade8c0e1c0d9bf
Le point de réflexion à ce moment-là était que la performance ne sortait pas, mais après un examen attentif, il semble que les réglages des paramètres étaient incorrects. Alors, après y avoir réfléchi, j'ai essayé différentes choses.
Pour une description de Dist-Keras lui-même, veuillez vous référer au précédent Post, mais le point est Keras fonctionnant sur un cluster Spark. J'ai fait de cette image une image Docker pour faciliter la mise à l'échelle.
Le Dockerfile est disponible sur GitHub. https://github.com/shibuiwilliam/distkeras-docker
Cette fois, je voudrais vérifier Dist-Keras sur Docker sur un seul hôte et plusieurs hôtes pour améliorer les performances. La dernière fois, j'ai lancé plusieurs conteneurs sur un seul hôte pour créer un cluster Spark. Cette fois, je vais augmenter le motif.
C'est MNIST qui fonctionne. Le programme d'apprentissage MNIST est personnalisé et utilisé tel que fourni par dist-keras.
Validez sur un seul hôte et sur plusieurs hôtes. Dans chaque cas, la configuration est Spark Master + Worker, et le nombre de travailleurs et les spécifications des travailleurs sont ajustés. Dans le cas du multi-hôte, il y a deux serveurs. L'hôte utilise m4.xlarge d'AWS EC2 CentOS 7.3.
no | hosts | workers | resources |
---|---|---|---|
1 | single | 1 | 1 processor, 2GB RAM |
2 | single | 2 | 2 processors, 5GB RAM |
3 | single | 3 | 1 processor, 3GB RAM |
4 | multihost | 2 | 2 processors, 5GB RAM |
5 | multihost | 2 | 3 processors, 8GB RAM |
6 | multihost | 4 | 2 processors, 5GB RAM |
L'image d'un seul hôte ressemble à ceci. Le nombre de conteneurs Docker varie en fonction des conditions de vérification.
Dans le cas d'un seul hôte, démarrez plusieurs conteneurs Docker sur le même hôte.
# 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
Le maître Spark lance le maître et le worker Spark, et l'esclave Spark lance le worker uniquement.
# 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}
Ensuite, personnalisez le programme MNIST avec Spark Master. L'exemple de code MNIST est fourni par Dist-Keras. Le répertoire est / opt / dist-keras / examples, qui contient les exemples de données et programmes suivants.
[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
Copiez le fichier d'origine, sauvegardez-le et appliquez les modifications suivantes.
cp mnist.py mnist.py.bk
Ajoutez ce qui suit au début.
from pyspark.sql import SparkSession
Modifiez les paramètres Spark pour cet environnement. L'intention du changement est la suivante. --Utilisation de Spark2 --Utilisation de l'environnement local --Définir l'URL principale dans l'environnement local
# 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
Modifiez la mémoire du travailleur pour qu'elle corresponde aux critères de validation.
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");
Vous pouvez ensuite l'exécuter sur le Spark Master avec python mnist.py
.
La configuration multi-hôte ressemble à ceci.
Le multi-hôte nécessite que le conteneur Docker soit connecté via un réseau de superposition. Veuillez consulter les informations suivantes pour savoir comment créer un réseau Docker avec plusieurs hôtes. http://knowledge.sakura.ad.jp/knowledge/4786/ http://christina04.hatenablog.com/entry/2016/05/16/065853
Je n'écrirai ici que ma procédure. Préparez host1 et host2 dans EC2, installez etcd sur host1 et démarrez-le.
yum -y install etcd
vi /etc/etcd/etcd.conf
systemctl enable etcd
systemctl start etcd
Ensuite, ajoutez les paramètres docker-network à l'hôte1 et à l'hôte2.
# 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"}
Maintenant que la connexion réseau entre les dockers est possible, créez un réseau docker avec host1. Ici, créez un réseau docker appelé test1 sur le sous-réseau 10.0.1.0/24.
# for host1
docker network create --subnet=10.0.1.0/24 -d overlay test1
Enfin, exécutez docker network ls
et c'est OK si le réseau test1 est ajouté.
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
Ajoutez ensuite un conteneur Docker au réseau test1. Déployons un conteneur Docker sur chacun des hôtes host1 et host2.
# 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
Vous avez maintenant déployé deux conteneurs Docker sur le réseau test1 avec plusieurs hôtes.
Après cela, démarrez le maître Spark et le worker Spark dans la même procédure que pour un seul hôte, éditez MNIST.py et exécutez python mnist.py
.
C'est le résultat de la vérification des performances de chaque configuration. Cette fois, nous mesurons le temps nécessaire pour terminer (secondes).
no. | hosts | workers | resources | time in second |
---|---|---|---|---|
1 | single | 1 | 1 processor, 2GB RAM | 1615.63757 |
2 | single | 2 | 2 processors, 5GB RAM | 1418.56935 |
3 | single | 3 | 1 processor, 3GB RAM | 1475.84212 |
4 | multihost | 2 | 2 processors, 5GB RAM | 805.382518 |
5 | multihost | 2 | 3 processors, 8GB RAM | 734.290324 |
6 | multihost | 4 | 2 processors, 5GB RAM | 723.878466 |
Les performances sont meilleures avec le multi-hôte. Je pense que la quantité de ressources gratuites fait simplement une différence dans les performances. La vérification 2 et la vérification 4 ont les mêmes paramètres pour la configuration du conteneur Docker et les ressources utilisées par les travailleurs, mais il y a toujours une différence de 600 secondes. La comparaison de la validation 1 et de la validation 2, ou de la validation 4 et de la validation 5 et de la validation 6 ne semble pas faire une grande différence dans le nombre de workers Spark et la quantité de ressources elles-mêmes. Si vous souhaitez améliorer considérablement les performances, il est préférable de le rendre multi-hôte obéissant.
[PostScript du 26/05/2017] Clustered avec Kubernetes. http://qiita.com/cvusk/items/42a5ffd4e3228963234d
Recommended Posts