理解和实现分布式TensorFlow集完整教程
⼿把⼿教你搭建分布式集,进⼊⽣产环境的TensorFlow
分布式TensorFlow简介
tensorflow版本选择
前⼀篇我们介绍了分布式TensorFlow的基本概念,现在我们可以动⼿搭建⼀个真正的分布式TensorFlow集。
分布式TensorFlow集由多个服务端进程和客户端进程组成,在某些场景下,服务端和客户端可以写到同⼀个Python⽂件并起在同⼀个进程,但为了简化代码让⼤家更好理解分布式架构,我们将启动两个worker并使⽤单独的客户端进程。
确认TensorFlow版本
⾸先我们需要安装和确认TensorFlow的版本,注意0.8版本以前的TensorFlow不⽀持分布式,使⽤以前版本需要重新合Patch和打包。
python -c  "import tensorflow; print(tensorflow.__version__)"
使⽤TensorFlow容器
如果本地已安装Docker,通过容器使⽤TensorFlow环境更加简单,只需⼀⾏命令。
sudo docker run -it tensorflow/tensorflow bash
Docker除了实现资源隔离,还可以管理不同版本的环境,例如可以很容易试⽤最新的RC版本。
sudo docker run -it tensorflow/tensorflow:r0.9rc0 bash
实现TensorFlow服务端
很多开发者读过TensorFlow官⽅的Distributed Guide,想把分布式TensorFlow运⾏起来却⼗分困难,主要原因是官⽅⽂档没有提供完整的例⼦,⽽且提供的代码⽚段只能在0.9中运⾏,因此很多⼈尝试修改那段代码还是跑不起来。
其实分布式TensorFlow使⽤⾮常简单,我们并不需要⼀个通⽤的程序,只要⽤⼏⾏代码分别实现服务端和客户端即可,最简单的服务端代码如下worker1.py。
import tensorflow as tf
worker1 = "10.235.114.12:2222"
worker2 = "10.235.114.12:2223"
worker_hosts = [worker1, worker2]
cluster_spec = tf.train.ClusterSpec({ "worker": worker_hosts})
server = tf.train.Server(cluster_spec, job_name="worker", task_index=0)
server.join()
这⾥我们定义了两个worker,其中job名都是“worker”,官⽅⽂档中还定义了名为“ps”的job,实际上有没有都可以,⽽worker可以是本地不同端⼝的两个进程或者多台服务器上的进程。
为了模拟分布式环境,我们编写worker2.py启动第⼆个worker,注意代码上稍有区别,因为index变了不能与前⾯的冲突,为了避免端⼝被容器隔离我们可以使⽤原来的Docker容器。
import tensorflow as tf
worker1 = "10.235.114.12:2222"
worker2 = "10.235.114.12:2223"
worker_hosts = [worker1, worker2]
cluster_spec = tf.train.ClusterSpec({ "worker": worker_hosts})
server = tf.train.Server(cluster_spec, job_name="worker", task_index=1)
server.join()
可以看到worker1和worker2分别监听本地的2222和2223端⼝,接下来可以单独写客户端应⽤,连接这两个targe即可。
实现TensorFlow客户端
Client的代码我们写得稍微复杂些,就是构造写线性数据,其中斜率是2、截距是10,如果梯度下降算法正确的话最终w和b的输出应该也接近2和10。
如我们所料,最终结果相当接近2和10,同时指定了第⼀个worker的CPU来执⾏梯度下降的算法,通过cluster spec我们还可以定义更灵活的集,客户端也可以通过"tf.device"来动态指定CPU和GPU计算资源。在⽣产环境下,官⽅推荐使⽤ps服务器存储Variables,⽽ps其实是和我们定义的worker⼀样,只是job名不同,架构可以参见官⽅⽂档的tasks图。
最后总结
希望通过这个完整的使⽤教程,⼤家都能亲⾃实现分布式TensorFlow集,并且编写灵活的服务端和客户端应⽤。
⽽在搭建过程中,⼤家可能发现TensorFlow只是⼀个深度学习的Library,我们需要实现和部署服务端、客户端应⽤,⽽在集定义中存在⼀个较严重的问题,就是cluster spec需要在进程启动时指定,⽆法实现动态的扩容或缩容,这个问题社区希望通过引⼊Kubernetes集管理⼯具来解决。还有⼀个问题就是我们的服务端应⽤启动时只能bind localhost,我们也在Github建了对应Issue,如果⼤家都这些问题感兴趣,也请继续关注我和我们后续的⽂章。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。