几个小时 几行代码 简单 直白 tensorflow 分布式代码实战

本文主要是介绍几个小时 几行代码 简单 直白 tensorflow 分布式代码实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

北京又下雪了,这个2020年开启的方式太沉重了。

注意,市面上普遍的tf分布式代码,我实测都有一个问题,如果你租用GPU资源请务必警惕这个问题会让你白花钱。如果你用的自己的资源,那应该是没有太大问题的。具体请看(https://blog.csdn.net/u013249853/article/details/104385793

好烦,每次发文都要审核,链接就得等他审核完了上,好麻烦,看来我得另外找个网站写博客了。

我本人对tf并不精通。分布式听起来也很复杂。而且我要做的是将deeplabv3+的代码做成分布式的。也就是多个节点,相当于用两台服务器的gpu。听起来很麻烦,实际上居然很简单。而我自己也是花了几个小时从什么都不懂到代码跑起来。

这个教程目的是以tensorflow为例,将分布式细节写出来,补充一下网上教程没有的东西。

很多教程写了特别长的文字,我认为画图更简单。本教程尽量简短,好懂,并且有代码。只是基础教程。

理论(特短,够用)

台电脑=服务器=server是一个节点,包含了个GPU。首先分布式的方式就是让台电脑上的gpu共同干活。

分布式工作分为两个部分,parameter server(ps)以及worker。眼熟ps与worker,因为这个是工作,每个server,都得干活,所以只能是从这两个工作里面选择。ps的工作类似于存储参数,而损失的计算,梯度的决定都是有worker进行的。这个对代码的影响就是,ps节点其实完全可以由cpu来做。worker必须由gpu做。

 

整体结构如图:一共四个sever,每个sever假设包含4个GPU,下图一共16个GPU。两个server工作是ps,两个sever的工作是worker,这个name其实没有在代码中配置,所以不用理会。server同做一个工作,也需要区分的,所以又引入了task,并且有task id。这里只是演示一下job(ps,worker)和server(节点)的关系。

代码

代码的讲解是踩点来的。就是怎么用代码互相交流。

从理论上看,我们需要一些节点,并且给他们分配工作。

所以做一下程序入口接受参数(节点都是是谁,给什么工作了),我比较喜欢接收参数,不喜欢在代码里面写死。因为flags是tf基础,不想解释增加长度。

每个节点都得被单独通知,并且单独运行,这意味着如果你有一个ps,两个worker(一般用一个ps即可),你得在bash命令里:

python train.py --ps都谁(ps_hosts) --worker都谁(woker_hosts) --我被分配干啥(job_name) --我是第几个干这活的(task_index)

python train.py --ps都谁(ps_hosts) --worker都谁(woker_hosts) --我被分配干啥(job_name) --我是第几个干这活的(task_index)

python train.py --ps都谁(ps_hosts) --worker都谁(woker_hosts) --我被分配干啥(job_name) --我是第几个干这活的(task_index)

就是输入三次,跑三次,同时。ps和worker都会等你输完了在一起工作,毕竟要等同伴。

下面是一个节点需要知道的消息。

flags = tf.app.flags
flags.DEFINE_integer('task_index', 0, 'The task ID.0 then is cheif session')
flags.DEFINE_string("ps_hosts", "g0101:2222", "ps hosts")
flags.DEFINE_string("worker_hosts", "g0101:2223,g0102:2224", "worker hosts")
flags.DEFINE_string("job_name", "worker", "'ps' or'worker'")

这四个东西怎么用需要看下面的代码,不要着急。不过我们可以看出,上面有一个ps server(节点)g0101:2222(可以当做该节点的名字),以及两个worker节点,g0101:2223+g0102:2224. 这里需要插播一下节点工作的时候是知道都有哪些节点一起工作,并且大家都是做什么任务的。

 

传参的时候是这样写的,这个节点需要知道的消息:

下面分别写下ps工作节点与worker工作节点传参。

ps:

python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2222" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="ps" \--task_index="0"

 然后节点就知道自己被分配了ps工作,只有一个ps节点(ps_hosts就一个,逗号是分隔符)。自己就是第一个。还有两个worker给自己打工

worker1:

python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2222" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="worker" \--task_index="1"

然后节点就知道自己被分配了worker工作,并且知道有两个worker,自己是第二个(task_index="1",计数从零开始,所以是第二个)。并且知道ps节点是谁。worker0当然就是类比着来。

python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2222" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="worker" \--task_index="0"

这里注意,我写的ps单独用了一个节点,如果想节省一下gpu,那么就写:

ps:

CUDA_VISIBLE_DEVICES=""
python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2223" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="ps" \--task_index="0"

worker1:

python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2223" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="worker" \--task_index="1"

注意看CUDA_VISIBLE_DEVICES,这时ps用的是worker1的CPU了。

 

然后需要建立一个cluster。需要用的是

  ps_hosts=FLAGS.ps_hosts.split(",")worker_hosts=FLAGS.worker_hosts.split(",")cluster=tf.train.ClusterSpec({"ps":ps_hosts,"worker":worker_hosts})server=tf.train.Server(cluster,job_name=FLAGS.job_name,task_index=FLAGS.task_index)if FLAGS.job_name == "ps":server.join()elif FLAGS.job_name =="worker":graph = tf.Graph()with graph.as_default():with tf.device(tf.train.replica_device_setter(worker_device="/job:worker/task:%d" % (FLAGS.task_index),cluster=cluster)):

with下面就是正常的dataset的设置,config的设置,并不是分布式独有的,所以省略了。而且是deeplab代码(改完可跑),所以建议看tf官方简单实例,一定看完哦,根本不长。

然后在session 里面的参数:master和一般设置不一样。

            with tf.train.MonitoredTrainingSession(master=server.target,

运行

输入的命令大家已经看到了,的确是需要输三遍bash 命令运行同一个python,但是由于分配的工作不同,所以是不一样的。

就是这个,还差两个worker。

python "${WORK_DIR}"/train_cloud.py \  
--ps_hosts="g0101:2222" \--worker_hosts="g0101:2223,g0102:2224" \--job_name="ps" \--task_index="0"

然后节点具体叫什么,这个需要问你的服务器管理员。你用我这个肯定不好使。

batchsize等的设置,每个节点,都要单独配置参数,比如worker0包含了一个GPU,worker1包含了两个GPU,那你的batchsize肯定是worker1更多。这个时候就把两个节点视作独立的。因为他们只能看到自己内部包含了什么设备(GPU),他虽然知道有个worker0和自己一起工作,却不知道worker0内部有什么设备。

输出与检验

虽然运行成功,但是怎么验证是否一起工作了呢?万一是各做各的就完蛋了。所以我又用deeplabv3+做了验证,如果batchsize不足的话,batch normalization的存在会使结果难看。

所以其输出是有三个ps0.out,worker0.out,worker1.out

我截一下图:

ps0,我用的就是cpu

 

worker0

worker1:

因为其实我有四个worker,这里只贴了两个。

参考:

https://www.youtube.com/embed/la_M6bCV91M

https://github.com/tensorflow/examples/blob/master/community/en/docs/deploy/distributed.md

https://henning.kropponline.de/2017/03/19/distributing-tensorflow/

https://zhuanlan.zhihu.com/p/35083779

https://www.jianshu.com/p/fdb93e44a8cc

这篇关于几个小时 几行代码 简单 直白 tensorflow 分布式代码实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128401

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

每天认识几个maven依赖(ActiveMQ+activemq-jaxb+activesoap+activespace+adarwin)

八、ActiveMQ 1、是什么? ActiveMQ 是一个开源的消息中间件(Message Broker),由 Apache 软件基金会开发和维护。它实现了 Java 消息服务(Java Message Service, JMS)规范,并支持多种消息传递协议,包括 AMQP、MQTT 和 OpenWire 等。 2、有什么用? 可靠性:ActiveMQ 提供了消息持久性和事务支持,确保消

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直