TensorFlow for distributed
TensorFlow for distributed
本目录包括了运行时分布式TensorFlow的实现,其底层使用了gRPC 作为进程内通信的支持库。
Quick start
首先,需要构建一个TensorFlow的服务端可执行版本(grpc_tensorflow_server
) 以及一个基于gRPC的客户端。目前只能基于源代码进行自构建, 但是会包含在未来发布的二进制版本中。可以使用如下命令进行构建:
# CPU-only build.
$ bazel --output_base=/data/tensorflow_distributed build -c opt //tensorflow/core/distributed_runtime/rpc:grpc_tensorflow_server
bazel --output_base=/home/data/tensorflow_distributed build -c opt //tensorflow/core/distributed_runtime/rpc:grpc_tensorflow_server
# GPU build.
$ cd /data/
tensorflow
$ bazel
--output_base=/data/tensorflow_distributed build -c opt --config=cuda //tensorflow/core/distributed_runtime/rpc:grpc_tensorflow_server
如果是从最新的源代码创建的Python依赖包,它会自动包含一个基于gRPC的客户端。如果使用的是一个之前发布的二进制版本,需要根据这个安装说明来重新编译安装。在你成功地构建了分布式的TensorFlow组件之后,可以通过如下方式来启动服务器并且判断你的安装是否成功:
# Start a TensorFlow server as a single-process "cluster".
#
启动示例1:
$
/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf1:2222;tf1:2223' --job_name=ps --task_index=0 &
$
/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf1:2222;tf1:2223' --job_name=ps --task_index=1 &
启动示例2:
$/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf3:2222;tf4:2223','wk|tf3:2224;tf4:2225' --job_name=ps --task_id=0 &(tf3上启动)
$/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf3:2222;tf4:2223','wk|tf3:2224;tf4:2225' --job_name=ps --task_id=1 &(tf4上启动)
$/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf3:2222;tf4:2223','wk|tf3:2224;tf4:2225' --job_name=wk --task_id=0 &(tf3上启动)
$/data/tensorflow_distributed/tensorflow/bazel-out/local_linux-opt/bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server --cluster_spec='ps|tf3:2222;tf4:2223','wk|tf3:2224;tf4:2225' --job_name=wk --task_id=1 &(tf4上启动)
然后启动Python的交互器并且启动一个Session:
$ python
>>> import tensorflow as tf
>>> c = tf.constant("Hello, distributed TensorFlow!")
>>> sess = tf.Session("grpc://localhost:2222")
>>> sess.run(c)
'Hello, distributed TensorFlow!'
补充:安装完后需要重新登录服务器,否则出现无法import tensorflow
集群定义
命令行参数 grpc_tensorflow_server
定义了集群之间的关系. 参数 --cluster_spec
决定了集群中工作对象的多少, 譬如有一系列的jobs, 而每个jobs又包含了多个task 终端。 所有集群中的处理过程都必须设置相同的 --cluster_spec
参数, 例子如下:
`local\ | localhost:2222` | /job:local/task:0 |
|
`local\ | localhost:2222;localhost:2223` | /job:local/task:0 `/job:local/task:1` |
|
`worker\ | worker0:2222;worker1:2222;worker2:2222,``ps\ | ps0:2222;ps1:2222` | /job:worker/task:0 `/job:worker/task:1/job:worker/task:2 /job:ps/task:0`/job:ps/task:1 |
--cluster_spec='...' |
Available tasks
|
---|
还有 --job_name
与 --task_index
标志位指明了哪些任务会运行在当前处理过程上。 具体而言,--job_name=local --task_index=0
意思就是该过程会被标志为/job:local/task:0
, 然后所有在该过程上的TensorFlow的设备都会使用这个前缀。
N.B.
手动来指明这些运行参数可能是非常冗长的,特别是对一个大型集群而言。我们正在研发可以程式化启动的工具,譬如使用一些类似于Kubernetes集群管理器。如果有啥集群管理工具你觉得挺好的希望加入进来,可以在GitHub issue上提出你的建议。
标注模型中的分布式设备
为了将某个操作放在某个特殊的处理过程上,在分布式环境下依然可以使用tf.device()
函数,之前是用来指明是放在CPU还是GPU上的。譬如:
with tf.device("/job:ps/task:0"):
weights_1 = tf.Variable(...)
biases_1 = tf.Variable(...)
with tf.device("/job:ps/task:1"):
weights_2 = tf.Variable(...)
biases_2 = tf.Variable(...)
with tf.device("/job:worker/task:7"):
input, labels = ...
layer_1 = tf.nn.relu(tf.matmul(input, weights_1) + biases_1)
logits = tf.nn.relu(tf.matmul(layer_1, weights_2) + biases_2)
# ...
train_op = ...
with tf.Session("grpc://worker7:2222") as sess:
for _ in range(10000):
sess.run(train_op)
在上面的例子中,Variables在job ps
的两个task上被创建,然后计算密集型的部分创建在job work
上。TensorFlow会自动地在不同的job之间传输数据。(从job
到work
是前向传递,而从worker
到ps
是梯度应用)。
Replicated Computation
一个常见的训练配置(数据并行训练)包含了job ps
上共享参数以及job work
上的多个任务来训练相同的模型。每个task一般会运行在不同的机器上。现在还是有很多办法可以在TensorFlow中来实现这一种结构的,我们未来也会提供更简单的实现方式,主要途径有:
构建单一的包含了一系列参数的图(in
tf.Variable
nodes pinned to/job:ps
), 并且创建多个模型的副本来映射到/job:worker
中的不同tasks。每个model的副本有一个不同的train_op
,并且对于每个workeri
而言一个或者多个的客户端线程可以调用sess.run(train_ops[i])
。这种方法使用了单一的tf.Session
,它的工作目标是集群中的某个workers。As above, but where the gradients from all workers are averaged. See the
CIFAR-10 multi-GPU trainer
for an example of this form of replication. The implements synchronous training
另一种分布式训练器的方法使用多张图,一张图对应一个worker,并且每张图都包含了一系列的参数的集合(
/job:ps
)和一份模型的赋值。而容器的机制就是在不同的图之间共享变量:一旦某个变量构造完成,可选的container
参数会由图中每份复制的相同值来决定。对于较大的模型而言,这种方法会更加有效,毕竟整个图更小了一点。
这种方法使用多个tf.Session
对象:每个worker过程都会包含一个,不过不同的Session会指向不同的目标worker。这个tf.Session
对象即可以在单一的Python客户端中创建,也可以在多个客户端中创建。
术语
Client
一个典型的客户端一般会构建一个TensorFlow的图并且使用tensorflow::Session
来完成与集群的交互。客户端一般会用Python或者C++编写,一般来说一个客户端可以同时与多个服务端进行交互(参考上文的重复训练),并且一个服务端也可以同时服务于多个客户端。
Cluster
一个TensorFlow集群会包含一个或者多个TensorFlow的服务端,被切分为一系列命名的job,而每个job又会负责一系列的tasks。一个集群一般会专注于一个相对高层的目标,譬如用多台机器并行地训练一个神经网络。
Job
一个job会包含一系列的致力于某个相同目标的task。譬如,一个叫ps
(意思是参数服务)的job会用于处理存储于更新Variables相关的工作。而一个叫worker
的job会用于承载那些用于计算密集型的无状态节点。一般来说一个job中的tasks会运行在不同的机器中。
Master service
Master Service是一个RPC服务用于与一系列远端的分布式设备进行交互。Master Service实现了tensorflow::Session
接口, 并且用来协调多个worker service。
Task
一个Task一般会关联到某个单一的TensorFlow服务端的处理过程,属于一个特定的job并且在该job的任务列表中有个唯一的索引。
TensorFlow server
用于运行grpc_tensorflow_server的处理过程,是一个集群中的一员,并且想外暴露了一个Master Service与一个Worker Service。
Worker service
一个执行部分TensorFlow图部分内容的RPC服务。
————————————————————————————————————————————
运行实例
部署文件 mlp_mnist_dist.py 到安装tensorflow的机器例如 10.100.208.23/24
分别在机器上运行
在 10.100.208.23上运行
python mlp_mnist_dist.py --ps_hosts=10.100.208.23:2222,10.100.208.23:2223 --worker_hosts=10.100.208.24:2224,10.100.208.24:2225 --job_name=ps --task_index=0
python mlp_mnist_dist.py --ps_hosts=10.100.208.23:2222,10.100.208.23:2223 --worker_hosts=10.100.208.24:2224,10.100.208.24:2225 --job_name=ps --task_index=1
在10.100.208.24上运行
python mlp_mnist_dist.py --ps_hosts=10.100.208.23:2222,10.100.208.23:2223 --worker_hosts=10.100.208.24:2224,10.100.208.24:2225 --job_name=worker --task_index=0
python mlp_mnist_dist.py --ps_hosts=10.100.208.23:2222,10.100.208.23:2223 --worker_hosts=10.100.208.24:2224,10.100.208.24:2225 --job_name=worker --task_index=1
启动时需要互相依赖,所以会有连接失败的error,待所连接的进程启动后就可以了
运行后 ,只有一个worker会完成,日志如下
Extracting ./MNIST_data/train-images-idx3-ubyte.gz
Extracting ./MNIST_data/train-labels-idx1-ubyte.gz
Extracting ./MNIST_data/t10k-images-idx3-ubyte.gz
Extracting ./MNIST_data/t10k-labels-idx1-ubyte.gz
job : worker/0 step : 0 ,training accuracy : 0.96
——————————————————————————————————————————————
简单测试用例:
import tensorflow as tf
def main() :
with tf.device("/job:ps/task:0/cpu:0"):
a = tf.Variable(1)
with tf.device("/job:ps/task:0/cpu:1"):
b = tf.Variable(1)
with tf.Session("grpc://localhost:22223",config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)) as sess:
init_ab = tf.initialize_all_variables();
sess.run(init_ab)
result = sess.run(a+b)
print(result)
if __name__ == '__main__':
main()
——————————————————————————————————————————————
问题解决:
1.如果并没有 grpc_tensorflow_server
可执行文件的话可以用 ./tensorflow/tools/dist_test/server/grpc_tensorflow_server.py 代替
2.在指定device时指定了cpu/gpu如果报错
tensorflow.python.framework.errors.InvalidArgumentError: Cannot assign a device to node 'Variable_1': Could not satisfy explicit device specification '/job:ps/task:0/device:CPU:1' because no devices matching that specification are registered in this process; available devices: /job:ps/replica:0/task:0/cpu:0, /job:worker/replica:0/task:0/cpu:0
[[Node: Variable_1 = Variable[container="", dtype=DT_INT32, shape=[], shared_name="", _device="/job:ps/task:0/device:CPU:1"]()]]
解决方法 https://github.com/tensorflow/tensorflow/issues/2285
就是在生命session时加入参数 allow_soft_placement=True
例如 :with tf.Session("grpc://localhost:22223",config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)) as sess:
如果是用Supervisor
sess = sv.prepare_or_wait_for_session(server.target,config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True))
3.如果编译时发生错误
ERROR: error loading package 'tensorflow/core/distributed_runtime/rpc': Extension file not found. Unable to load package for '//google/protobuf:protobuf.bzl': BUILD file not found on package path.
在源码目录下 执行 git submodule update --init 命令来下载依赖
https://github.com/bazelbuild/bazel/issues/605
TensorFlow for distributed的更多相关文章
- Distributed TensorFlow
Distributed TensorFlow Todo list: Distributed TensorFlow简介 Distributed TensorFlow的部署与运行 对3个台主机做多卡GPU ...
- 从TensorFlow到PyTorch:九大深度学习框架哪款最适合你?
开源的深度学习神经网络正步入成熟,而现在有许多框架具备为个性化方案提供先进的机器学习和人工智能的能力.那么如何决定哪个开源框架最适合你呢?本文试图通过对比深度学习各大框架的优缺点,从而为各位读者提供一 ...
- TensorFlow 分布式实践
此wiki主要介绍分布式环境使用的一些条件,一直所要注意的内容: 确保在此之前阅读过TensorFlow for distributed 1.集群描述 当前tensorflow 的版本(0.8.0), ...
- docker下安装tensorflow
一,查找镜像 root@xushi:~# docker search tensorflow NAME DESCRIPTION STARS OFFICIAL AUTOMATED tensorflow/t ...
- CoRR 2018 | Horovod: Fast and Easy Distributed Deep Learning in Tensorflow
将深度学习模型的训练从单GPU扩展到多GPU主要面临以下问题:(1)训练框架必须支持GPU间的通信,(2)用户必须更改大量代码以使用多GPU进行训练.为了克服这些问题,本文提出了Horovod,它通过 ...
- [翻译] TensorFlow 分布式之论文篇 "TensorFlow : Large-Scale Machine Learning on Heterogeneous Distributed Systems"
[翻译] TensorFlow 分布式之论文篇 "TensorFlow : Large-Scale Machine Learning on Heterogeneous Distributed ...
- Why do people integrate Spark with TensorFlow even if there is a distributed TensorFlow framework?
https://www.quora.com/Why-do-people-integrate-Spark-with-TensorFlow-even-if-there-is-a-distributed-T ...
- tensorflow添加自定义的auc计算operator
tensorflow可以很方便的添加用户自定义的operator(如果不添加也可以采用sklearn的auc计算函数或者自己写一个 但是会在python执行,这里希望在graph中也就是c++端执行这 ...
- TensorFlow白皮书
TensorFlow [1] is an interface for expressing machine learning algorithms, and an implementation for ...
随机推荐
- 003-linux命令-文件和目录、查看文件内容-文本处理
文本处理 cat file1|command(sed,grep,awk,) > result.txt 合并一个文件的详细说明文本,并将简介写入一个新文件中 cat file1|command(s ...
- 初学git
初学git,总结了一点东西,可能有理解和操作的不到位的地方,还有就是这个是我之前写在word上的,因为CSDN上不能直接上传,所以拷贝的过程中也可能有其他问题.发的的朋友还望指正... 1.找到“参与 ...
- java poi生成excel(个人例子js-jsp-java)
js代码: function exportRepQudl(){ if(confirm("导出输出页面内容?")){ var id = $("input[name='id' ...
- vue-自定义全局键盘码
1.Vue.config.keyCodes.enter=13; //main.js中定义全局 <template> <div> <input v-model=" ...
- JVM内存管理(转)
转载出处:http://blog.csdn.net/wind5shy/article/details/8349559 模型 JVM运行时数据区域 JVM执行Java程序的过程中,会使用到各种数据区域, ...
- ssh tunnel 三种模式
环境介绍: 主机 位置 公网 内网IP 角色 host-a 局域网1 否 192.168.0.1 ssh client host-b 局域网2.公网 是 192.168.1.1 ssh server ...
- mybatis oracle 插入自增记录 获取主键值 写回map参数
网上搜了好多文章照着弄都返回不了主键给map, 实践证明要在传入的map参数里写回插入的主键,要这样写 <selectKey resultType="java.lang.Integer ...
- JMeter登录总是提示用户名不能为空的解决
已传入参数了呀,还是提示用户名不能为空 解决: 将url拼接上参数 --
- matplotlib画的图保存为emf格式
在用matplotlib保存图片时,发现不能直接保存为emf格式.百度有人说要先另存为svg格式,再使用INKSCAPE软件转换成emf格式.我试了一下,发现还是不行,后来,发现先用matplotli ...
- (已解决)Xcode 换电脑提示 Could not attach to pid:“XXXX”错误
在运行项目时出现了如下错误 (基本上重新启动项目即可) 紧接着再次运行又没有问题了. 稍微查询了一下得知,这个问题并不是由我们的操作引起的,有时就会莫名其妙的出现,但是有一些不同的情况 下面列出如何解 ...