分布式Tensorflow底层的通信是gRPC。gRPC首先是一个RPC,即远程过程调用,通俗的解释是:假设你在本机上执行一段代码num=add(a,b),它调用了一个过程call,然后返回了一个值num,你感觉这段代码只是在本机上执行的,但实际情况是,本机上的add方法是将参数打包发送给服务器,然后服务器运行服务器端的add方法,返回的结果再将数据打包返回给客户端。
TensorFlow集群就是一组任务,每个任务就是一个服务。服务由两个部分组成,第一部分是master,用于创建session,第二部分是worker,用于执行具体的计算。TensorFlow一般将任务分为两类job:一类叫参数服务器,parameter server,简称为ps,用于存储tf.Variable;一类就是普通任务,称为worker,用于执行具体的计算。
一般而言,机器学习的参数训练过程可以划分为两个类别:第一个是根据参数算算梯度,第二个是根据梯度更新参数。对于小规模训练,数据量不大,参数数量不多,一个CPU就足够了,两类任务都交给一个CPU来做。对于普通的中等规模的训练,数据量比较大,参数数量不多,计算梯度的任务负荷较重,参数更新的任务负荷较轻,所以将第一类任务交给若干个CPU或GPU去做,第二类任务交给一个CPU即可。对于超大规模的训练,数据量大、参数多,不仅计算梯度的任务要部署到多个CPU或GPU上,而且更新参数的任务也要部署到多个CPU。如果计算量足够大,一台机器能搭载的CPU和GPU数量有限,就需要多台机器来进行计算能力的扩展了。参数服务器是一套分布式存储,用于保存参数,并提供参数更新的操作。
1 TensorFlow集群创建
每个任务用一个ip:port表示。TensorFlow用tf.train.ClusterSpec表示一个集群信息。
import tensorflow as tf
cluster = tf.train.ClusterSpec({
"worker": [
"worker_task0.example.com:2222",# /job:worker/task:0 运行的主机
"worker_task1.example.com:2222",# /job:worker/task:1 运行的主机