基于Hadoop分布式集群YARN模式下的TensorFlowOnSpark平台搭建
1. 介绍
在过去几年中,神经网络已经有了很壮观的进展,现在他们几乎已经是图像识别和自动翻译领域中最强者[1]。为了从海量数据中获得洞察力,需要部署分布式深度学习。现有的DL框架通常需要为深度学习设置单独的集群,迫使我们为机器学习流程创建多个程序(见Figure 1)。拥有独立的集群需要我们在它们之间传递大型数据集,从而引起不必要的系统复杂性和端到端的学习延迟。
TensorFlow是Google公司刚刚发布不久一款用于数值计算和神经网络的深度学习框架。
TensorFlowOnSpark是yahoo今年刚开源的一个项目,目的就是充分发掘TensorFlow在现有的大数据集群上进行高效深度学习的能力,利用TensorFlowOnSpark,数据科学家和工程师们可以直接利用运行于CPU/GPU架构上的Spark或者Hadoop做分布式模型训练。该库支持把现有的TensorFlow程序切换到新的API,同时实现了模型训练的性能提升。
在开源公告里,雅虎说明了TensorFlowOnSpark想解决的问题,比如在深度神经网络训练中管理Spark数据管线之外的其他集群带来的运维负载,以网络I/O为瓶颈的数据集在训练集群的传入和传出,令人讨厌的系统复杂性,以及端到端的整体学习时延。TensorFlowOnSpark的工作和雅虎之前开源的CaffeOnSpark相似。现有的对TensorFlow和Spark的集成所做的努力,有DataBricks的TensorFrame,以及Amp Lab 的SparkNet,这些对于雅虎来说都是在正确方向上的迈进,但是在允许TensorFlow进程之间直接通信方面还是有所欠缺。雅虎的目标之一,是让TensorFlowOnSpark成为一个完全对Spark兼容的API,在一个Spark处理工作流里,其集成能力能跟SparkSQL、MLib以及其他Spark核心库一样好。
在架构上,它把给定TensorFlow算法和TensorFlow core放在一个Spark Executor中,并让TensorFlow任务能够通过TensorFlow的文件阅读器和QueueRunners直接获取HDFS数据,这是一种有着更少网络I/O以及“把计算带给数据”的方案。TensorFlowOnSpark在语义上就支持对执行器的端口预留和监听,对数据和控制函数的消息轮询,TensorFlow主函数的启动,数据注入,直接从HDFS读取数据的阅读器和queue-runner机制,通过feed_dict向TensorFlow注入Spark RDD,以及关机。
除了TensorFlowOnSpark,yahoo还在他们自己的分支上扩展了TensorFlow核心C++引擎以在Infiniband里使用RDMA,这个需求在TensorFlow主项目里被提出过还产生了相关讨论。雅虎的Andy Feng注意到,使用RDMA而不是gRPC来做进程间通信,在不同的网络里会带来百分之十到百分之两百不等的训练速度的提升[2]。
2.TensorFlowOnSpark核心技术点
- 轻松迁移所有现有的TensorFlow程序,<10行代码更改;
- 支持所有TensorFlow功能:同步/异步训练,模型/数据并行,推理和TensorBoard;
- 服务器到服务器的直接通信在可用时实现更快的学习;
- 允许数据集在HDFS和由Spark推动的其他来源或由TensorFlow拖动;
- 轻松集成您现有的数据处理流水线和机器学习算法(例如,MLlib,CaffeOnSpark);
- 轻松部署在云或内部部署:CPU和GPU,以太网和Infiniband[3]。
3.基于Hadoop分布式群YARN模式的搭建
官方指导链接:https://github.com/yahoo/TensorFlowOnSpark/wiki/GetStarted_YARN,这篇文章过于简略,很多地方都没有说明白,初学者会绕很多弯路,也许是因为这个项目刚刚开源不久,很多指导性的说明都没有。简言之,官网的 Instructions 略坑,搭建成功与否靠人品。
以下是本人实践成功的步骤:
3.1 环境准备
已经安装了 Spark 的 Hadoop 分布式集群环境(安装于 Ubuntu Server 系统),下表显示了我的集群环境( Spark 已经开启):
主机名 | ip | 用途 |
master | 192.168.0.20 |
ResourceManager NameNode SecondaryNameNode Master |
node1 | 192.168.0.21 |
DataNode NodeManager Worker |
node2 | 192.168.0.22 |
DataNode NodeManager Worker |
这里给大家推荐一个超详细的关于部署 Hadoop 完全分布式集群的博客:http://blog.csdn.net/dream_an/article/details/52946840[4]
3.2 在 Master 节点上进行:
(1) 安装 Python 2.7
这一步的是在本地文件夹里下载安装 Python ,目的是在进行任务分发的时候能够把这个 Python 和其他依赖环境(这里指的是包含 TensorFlow)同时分发给对应的 Spark executor ,所以这一步不是单纯的只安装 Python 。
#下载解压 Python 2.7
export PYTHON_ROOT=~/Python
curl -O https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz
tar -xvf Python-2.7..tgz
rm Python-2.7..tgz #在编译 Python 之前,需要完成以下工作,否则编译产生的 python 会出现没有 zlib 、没有 SSL 模块等错误
#安装 ruby , zlib , ssl 相关包
sudo apt install ruby
sudo apt install zlib1g,zlib1g.dev
sudo apt install libssl-dev #进入刚才解压的 Python 目录,修改 Modules/Setup.dist文件,该文件是用于产生 Python 相关配置文件的
cd Python-2.7.12
sudo vim Modules/Setup.dist
#去掉 ssl , zlib 相关的注释:
#与 ssl 相关:
#SSL=/usr/local/ssl
#_ssl _ssl.c \
# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
# -L$(SSL)/lib -lssl -lcrypto
#与 zlib 相关:
#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz #编译 Python 到本地文件夹 ${PYTHON_ROOT}
pushd Python-2.7.12
./configure --prefix="${PYTHON_ROOT}" --enable-unicode=ucs4
#./configure 这一步如果提示 "no acceptable C compiler" , 需要安装 gcc : sudo apt install gcc
make
make install
popd
rm -rf Python-2.7.12
#安装 pip
pushd "${PYTHON_ROOT}"
curl -O https://bootstrap.pypa.io/get-pip.py
bin/python get-pip.py
rm get-pip.py
#安装 pydoop
${PYTHON_ROOT}/bin/pip install pydoop
#这里安装 pydoop,若是提示错误:LocalModeNotSupported,直接下载资源包通过 setup 安装:
#资源包下载:https://pypi.python.org/pypi/pydoop
#tar -xvf pydoop-1.2.0.tar.gz
#cd pydoop-1.2.0
#python setup.py build
#python setup.py install
#安装 TensorFlow
${PYTHON_ROOT}/bin/pip install tensorflow
#这里安装 tensorflow ,不需要从源码进行编译安装,除非你需要 RDMA 这个特性
popd
(2) 安装 TensorFlowOnSpark
git clone https://github.com/yahoo/TensorFlowOnSpark.git
git clone https://github.com/yahoo/tensorflow.git
#从 yahoo 下载的 TensorFlowOnSpark 资源包里面 tensorflow 是空的文件夹,git 上该文件夹连接到了 yahoo/tensorflow ,这里需要我们将 tensorflow 拷贝到 TensorFlowO#nSpark 下面:
sudo rm -rf TensorFlowOnSpark/tensorflow/
sudo mv tensorflow/ TensorFlowOnSpark/
#上面 tensorflow 和 TensorFlowOnSpark 文件目录根据自己的实际情况修改,我的是在根目录下面,所以如上
(3) 安装编译 Hadoop InputFormat/OutputFormat for TFRecords
#安装以下依赖工具:
sudo apt install autoconf,automake,libtool,curl,make,g++,unzip,maven #先安装 protobuf
# git 上有详细说明:github上有详细的安装说明:https://github.com/google/protobuf/blob/master/src/README.md
#也可以参考链接:http://www.itdadao.com/articles/c15a1006495p0.html
#编译 TensorFlow 的 protos:
git clone https://github.com/tensorflow/ecosystem.git
cd ecosystem/hadoop
protoc --proto_path=/opt/TensorFlowOnSpark/tensorflow/ --java_out=src/main/java/ /opt/TensorFlowOnSpark/tensorflow/tensorflow/core/example/{example,
feature}.proto
mvn clean package
mvn install
#将上一步产生的 jar 包上传到 HDFS
cd target
hadoop fs -put tensorflow-hadoop-1.0-SNAPSHOT.jar
(4) 为 Spark 准备 Python with TensorFlow 压缩包
pushd "${PYTHON_ROOT}"
zip -r Python.zip *
popd
#将该压缩包上传到 HDFS
hadoop fs -put ${PYTHON_ROOT}/Python.zip
(5) 为 Spark 准备 TensorFlowOnSpark 压缩包
pushd TensorFlowOnSpark/src
zip -r ../tfspark.zip *
popd
环境基本搭建完成。
4. 测试[5]
1)准备数据
下载、压缩mnist数据集
mkdir ${HOME}/mnist
pushd ${HOME}/mnist >/dev/null
curl -O "http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz"
curl -O "http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"
curl -O "http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz"
curl -O "http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz"
zip -r mnist.zip *
popd >/dev/null
2)feed_dic方式运行,步骤如下
# step 设置环境变量
export PYTHON_ROOT=~/Python
export LD_LIBRARY_PATH=${PATH}
export PYSPARK_PYTHON=${PYTHON_ROOT}/bin/python
export SPARK_YARN_USER_ENV="PYSPARK_PYTHON=Python/bin/python"
export PATH=${PYTHON_ROOT}/bin/:$PATH
export QUEUE=default # step 上传文件到hdfs
hdfs dfs -rm /user/${USER}/mnist/mnist.zip
hdfs dfs -put ${HOME}/MLdata/mnist/mnist.zip /user/${USER}/mnist/mnist.zip # step 将图像文件(images)和标签(labels)转换为CSV文件
hdfs dfs -rm -r /user/${USER}/mnist/csv
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 4G \
--archives hdfs:///user/${USER}/Python.zip#Python,hdfs:///user/${USER}/mnist/mnist.zip#mnist \
TensorFlowOnSpark/examples/mnist/mnist_data_setup.py \
--output mnist/csv \
--format csv # step 训练(train)
hadoop fs -rm -r mnist_model
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 8G \
--py-files ${HOME}/TensorFlowOnSpark/tfspark.zip,${HOME}/TensorFlowOnSpark/examples/mnist/spark/mnist_dist.py \
--conf spark.dynamicAllocation.enabled=false \
--conf spark.yarn.maxAppAttempts= \
--conf spark.yarn.executor.memoryOverhead= \
--archives hdfs:///user/${USER}/Python.zip#Python \
--conf spark.executorEnv.LD_LIBRARY_PATH="$JAVA_HOME/jre/lib/amd64/server" \
${HOME}/TensorFlowOnSpark/examples/mnist/spark/mnist_spark.py \
--images mnist/csv/train/images \
--labels mnist/csv/train/labels \
--mode train \
--model mnist_model # step 推断(inference)
hadoop fs -rm -r predictions
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 8G \
--py-files ${HOME}/TensorFlowOnSpark/tfspark.zip,${HOME}/TensorFlowOnSpark/examples/mnist/spark/mnist_dist.py \
--conf spark.dynamicAllocation.enabled=false \
--conf spark.yarn.maxAppAttempts= \
--conf spark.yarn.executor.memoryOverhead= \
--archives hdfs:///user/${USER}/Python.zip#Python \
--conf spark.executorEnv.LD_LIBRARY_PATH="$JAVA_HOME/jre/lib/amd64/server" \
${HOME}/TensorFlowOnSpark/examples/mnist/spark/mnist_spark.py \
--images mnist/csv/test/images \
--labels mnist/csv/test/labels \
--mode inference \
--model mnist_model \
--output predictions # step 查看结果(可能有多个文件)
hdfs dfs -ls predictions
hdfs dfs -cat predictions/part-
hdfs dfs -cat predictions/part-
hdfs dfs -cat predictions/part- #网页方式,查看spark作业运行情况,这里的 ip 地址是 master 节点的 ip
http://192.168.0.20:8088/cluster/apps/
3) queuerunner方式运行,步骤如下
# step 设置环境变量
export PYTHON_ROOT=~/Python
export LD_LIBRARY_PATH=${PATH}
export PYSPARK_PYTHON=${PYTHON_ROOT}/bin/python
export SPARK_YARN_USER_ENV="PYSPARK_PYTHON=Python/bin/python"
export PATH=${PYTHON_ROOT}/bin/:$PATH
export QUEUE=default # step 上传文件到hdfs
hdfs dfs -rm /user/${USER}/mnist/mnist.zip
hdfs dfs -rm -r /user/${USER}/mnist/tfr
hdfs dfs -put ${HOME}/MLdata/mnist/mnist.zip /user/${USER}/mnist/mnist.zip # step 将图像文件(images)和标签(labels)转换为TFRecords
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 4G \
--archives hdfs:///user/${USER}/Python.zip#Python,hdfs:///user/${USER}/mnist/mnist.zip#mnist \
--jars hdfs:///user/${USER}/tensorflow-hadoop-1.0-SNAPSHOT.jar \
${HOME}/TensorFlowOnSpark/examples/mnist/mnist_data_setup.py \
--output mnist/tfr \
--format tfr # step 训练(train)
hadoop fs -rm -r mnist_model
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 4G \
--py-files ${HOME}/TensorFlowOnSpark/tfspark.zip,${HOME}/TensorFlowOnSpark/examples/mnist/tf/mnist_dist.py \
--conf spark.dynamicAllocation.enabled=false \
--conf spark.yarn.maxAppAttempts= \
--conf spark.yarn.executor.memoryOverhead= \
--archives hdfs:///user/${USER}/Python.zip#Python \
--conf spark.executorEnv.LD_LIBRARY_PATH="$JAVA_HOME/jre/lib/amd64/server" \
${HOME}/TensorFlowOnSpark/examples/mnist/tf/mnist_spark.py \
--images mnist/tfr/train \
--format tfr \
--mode train \
--model mnist_model # step 推断(inference)
hadoop fs -rm -r predictions
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--deploy-mode cluster \
--queue ${QUEUE} \
--num-executors \
--executor-memory 4G \
--py-files ${HOME}/TensorFlowOnSpark/tfspark.zip,${HOME}/TensorFlowOnSpark/examples/mnist/tf/mnist_dist.py \
--conf spark.dynamicAllocation.enabled=false \
--conf spark.yarn.maxAppAttempts= \
--conf spark.yarn.executor.memoryOverhead= \
--archives hdfs:///user/${USER}/Python.zip#Python \
--conf spark.executorEnv.LD_LIBRARY_PATH="$JAVA_HOME/jre/lib/amd64/server" \
${HOME}/TensorFlowOnSpark/examples/mnist/tf/mnist_spark.py \
--images mnist/tfr/test \
--mode inference \
--model mnist_model \
--output predictions # step 查看结果(可能有多个文件)
hdfs dfs -ls predictions
hdfs dfs -cat predictions/part-
hdfs dfs -cat predictions/part-
hdfs dfs -cat predictions/part- #网页方式,查看spark作业运行情况,这里的 ip 地址是 master 节点对应的 ip
http://192.168.0.20:8088/cluster/apps/
5. 参考资料
[1] https://databricks.com/blog/2016/01/25/deep-learning-with-apache-spark-and-tensorflow.html
[2] https://www.infoq.com/news/2017/03/tensorflow-spark
[3] http://blog.csdn.net/sinat_34233802/article/details/68942780
[4] http://blog.csdn.net/dream_an/article/details/52946840
[5] http://blog.csdn.net/hjh00/article/details/64439268
版权声明:本文未特殊标注为原创,未经博主允许不得转载。
基于Hadoop分布式集群YARN模式下的TensorFlowOnSpark平台搭建的更多相关文章
- 一脸懵逼学习Hadoop分布式集群HA模式部署(七台机器跑集群)
1)集群规划:主机名 IP 安装的软件 运行的进程master 192.168.199.130 jdk.hadoop ...
- 分布式集群HA模式部署
一:HDFS系统架构 (一)利用secondary node备份实现数据可靠性 (二)问题:NameNode的可用性不高,当NameNode节点宕机,则服务终止 二:HA架构---提高NameNode ...
- 超快速使用docker在本地搭建hadoop分布式集群
超快速使用docker在本地搭建hadoop分布式集群 超快速使用docker在本地搭建hadoop分布式集群 学习hadoop集群环境搭建是hadoop入门的必经之路.搭建分布式集群通常有两个办法: ...
- 暑假第二弹:基于docker的hadoop分布式集群系统的搭建和测试
早在四月份的时候,就已经开了这篇文章.当时是参加数据挖掘的比赛,在计科院大佬的建议下用TensorFlow搞深度学习,而且要在自己的hadoop分布式集群系统下搞. 当时可把我们牛逼坏了,在没有基础的 ...
- 使用Docker在本地搭建Hadoop分布式集群
学习Hadoop集群环境搭建是Hadoop入门必经之路.搭建分布式集群通常有两个办法: 要么找多台机器来部署(常常找不到机器) 或者在本地开多个虚拟机(开销很大,对宿主机器性能要求高,光是安装多个虚拟 ...
- CentOS6安装各种大数据软件 第四章:Hadoop分布式集群配置
相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...
- 使用docker搭建hadoop分布式集群
使用docker搭建部署hadoop分布式集群 在网上找了非常长时间都没有找到使用docker搭建hadoop分布式集群的文档,没办法,仅仅能自己写一个了. 一:环境准备: 1:首先要有一个Cento ...
- 大数据系列之Hadoop分布式集群部署
本节目的:搭建Hadoop分布式集群环境 环境准备 LZ用OS X系统 ,安装两台Linux虚拟机,Linux系统用的是CentOS6.5:Master Ip:10.211.55.3 ,Slave ...
- hadoop分布式集群的搭建
电脑如果是8G内存或者以下建议搭建3节点集群,如果是搭建5节点集群就要增加内存条了.当然实际开发中不会用虚拟机做,一些小公司刚刚起步的时候会采用云服务,因为开始数据量不大. 但随着数据量的增大才会考虑 ...
随机推荐
- 1599: [Usaco2008 Oct]笨重的石子
1599: [Usaco2008 Oct]笨重的石子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 795 Solved: 543[Submit][ ...
- 添加swagger api文档到node服务
swagger,一款api测试工具,详细介绍参考官网:http://swagger.io/ ,这里主要记录下怎么将swagger api应用到我们的node服务中: 1.任意新建node api项目, ...
- 【转】请求处理机制其二:Django中间件的解析
Middleware 开始工作了 get_response 做的第一件事就是遍历处理器的 _request_middleware 实例变量并调用其中的每一个方法,传入 HttpRequest 的实例作 ...
- web从入门开始(3)-----第一个网页
<meta>:是进行网页格式初始化的命令,确定网页使用的文本格式和编码格式 Background:中的路径,必须为相对路径 l HTML文本标记 <b>HTM文本</b ...
- Linux云自动化运维第二课
一.Linux系统结构 1.Linux是一个倒树结构.Linux中所有的东西都是文件.这些文件都在系统的顶级目录中"/","/"是根目录."/&quo ...
- ArcGIS API for JavaScript FeatureLayer服务属性编辑
首先说一下感想吧,刚入行时感觉深似海,掉到了GIS开发的陨石大坑里了,首先是学了小半年的Flex,用到了ArcGIS API for Flex,接着又是半年的ArcEngine开发,现在终于摸到了一点 ...
- JVM中堆内存和栈内存的区别
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
- Android 7.0(牛轧糖)新特性
Android 7.0(牛轧糖)新特性 谷歌正式在I/O大会现场详细介绍了有关Android 7.0的大量信息.目前,我们已经知道,新一代Android操作系统将支持无缝升级,能够通过Vulkan A ...
- JQ鼠标右键点击功能 兼容IE8
//阻止浏览器当前DIV默认右键事件 $("div").unbind("mousedown").bind("contextmenu", fu ...
- python安装paramiko需要的依赖
yum install gcc libffi-devel python-devel openssl-devel -y