`
m635674608
  • 浏览: 5041516 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

浅尝TensorFlow on Kubernetes

 
阅读更多

Distributed TensorFlow

2016年4月TensorFlow发布了0.8版本宣布支持分布式计算,这个特性,我们称之为Distributed TensorFlow。

这是非常重要的一个特性,因为在AI的世界里,训练数据的size通常会大到让人瞠目结舌。比如Google Brain实验室今年发表的论文OUTRAGEOUSLY LARGE NEURAL NETWORKS: THE SPARSELY-GATED MIXTURE-OF-EXPERTS LAYER中提到,下图中MOE Layer Model可以达到680亿个Parameters的规模,如此复杂的模型,如果只能单机训练,那耗时难于接受。通过Distributed TensorFlow,可以利用众多服务器构建TensorFlow Cluster来提高训练效率。

输入图片说明

关于Distributed TensorFlow的更多内容,请参考官方内容www.tensorflow.org/deplopy/distributed,这里给出Distributed TensorFlow结构图:

Why TensorFlow on Kubernetes

Distributed TensorFlow虽然提供了分布式能力,可以利用服务器集群加快训练,但是还有许多缺点,比如资源无法隔离、PS进程遗留问题等等,而这些正是Kubernetes所擅长的地方。下图是总结的你需要将TensorFlow运行在Kubernetes上的理由:

输入图片说明

对于我们来说,前期最大的用户痛点就是算法团队使用的HDFS Read性能不及预期,经过网上查找资料及我们自己简单的对比测试,发现***GlusterFS***可能是最适合我们的分布式存储了。因此在我们的TensorFlow on Kubernetes项目中使用GlusterFS来存放训练数据,worker将从GlusterFS中读取训练数据进行计算。

关于PS进程遗留问题,TensorFlow社区有很多讨论,但至今没有官方的实现方案,在Kubernetes中,这将比较好解决,在后面的Thinking小节中会单独讨论。

Integrated Architecture

输入图片说明

说明:

  • 支持Between-Graph和In-Graph两种replication场景;
  • PS Task通过Kubernetes Deployment来部署,Worker Task通过Kubernetes Job来部署,由Kubernetes service和KubeDNS来提供服务发现;
  • 每个TensorFlow Cluster都会通过StorageClass来Dynamic Provision PV,事先会先创建好通过Heketi对接Gluster集群的StorageClass;
  • GlusterFS集群通过Heketi来暴露rest api与Kubernetes进行交互,关于Heketi的部署,请参考官方文档;
  • 每个TensorFlow Cluster会最终创建两个PV,一个用来存放训练数据(挂载到容器内/data,对应TensorFlow --data_dir配置),一个用来存储训练日志(挂载到容器内/log,对应TensorFlow --log_path配置);
  • 每个用户会对应在Kubernetes中创建一个namespace;
  • 会给每个用户部署一个Jupyter Notebook Deployment和Service,Service通过NodePort暴露到集群外;
  • 有一个节点比较特殊,我们称之为User Node,这个节点通过Taint方式,保证会运行Pod,但是会通过kube-proxy来暴露集群内的service,比如上面的Jupyter Notebook service将只允许在这个节点暴露出去;
  • User Node节点存放着用户写的python算法,并可以通过http查看和下载这些算法文件,Between-Graph场景下,容器启动后将通过curl下载这些算法文件;
  • 会给没用用户创建一个Tensorboard Deployment和Service,Serivce通过NodePort暴露到集群外(同样只能在User Node暴露),Tensorboard Pod会挂着log PV,这样就能得到TensorFlow Graph。

Deploy Architecture

输入图片说明

整个系统涉及以下核心Components:

  • TensorFlow: 1.3.0
  • Kubernetes: 1.7.4
  • Docker: 1.12.6
  • Harbor: 1.1.2
  • Contiv netplugin: 0.1-12-23-2016.19-44-42.UTC
  • Keepalived: 1.3.5
  • Haproxy:1.7.8
  • Etcd2: 2.3.7
  • Etcd3: 3.2.1
  • Glusterfs: 3.10.5

网络方案:contiv netplugin + ovs + vlan.
日志方案:fluentd + Kafka + ES + Kibana.
监控方案:cadvisor + prometheus + Grafana.

CaaS的细节不在这里讨论,其实也是大家非常熟悉的方案了。

Demo

大家可以参考Kyle Bai的https://github.com/kairen/workshop413,他这里时候用NFS作为后端存储,需要改成你们自己的存储,大家自己去尝试吧,我这就不一步一步来了,好无聊。

这个Demo,我改成NodePort方式暴露Jupyter Nodebook,登录时输入正确的token即可:

输入图片说明

这是一个In-Graph集群,点击master_client.ipynb,可以看到具体的训练算法内容:

输入图片说明

点击执行,可以在下面看到输出:

输入图片说明

这只是个简单的Demo,实际使用上,自动化生成各个ps, worker, pvc对应的kubernetes yaml,使用域名进行服务发现,不然如果你使用IP的话,可能就需要利用Pod的ProStart Hook来反馈各个Task的IP了,这将比较麻烦。

Thinking

  • Q: PS进程遗留问题,在社区讨论比较多(issue 4173),结合Kubernetes,我们可以比较简单的来做到回收PS进程的目的。 A:在DevOps的TaaS模块中,针对每个TensorFlow Cluster都启动一个协程,检查计数器是否达到worker数量(worker是job运行的,down了以后,watch到job successed,则计数器加1),如果等于worker数,则表明训练结束,等待30s后,调用kubernetes apiserver接口将ps deployment/service删除,达到自动回收ps的效果;

  • Qworker是无状态的,ps是有状态的,而ps是无法进行checkpoint的,如何进行训练save和restore呢?
    A:worker虽然是无状态的,但是tf.train.Saver提供能力在worker上进行checkpoint,大概原理就是逐个从PS task中get Parameters,并进行save持久化。

  • Q怎么让用户指定ps和worker个数等少量参数,自动生成kubernetes yaml?
    A: 因为当前我们还没有针对TaaS做前端Portal,所以目前是通过jinja template来自动生成的(可以参考tensorflow/ecosystem/kubernetes),用户只要指定少量参数即可生成ps和worker需要的kubernetes yaml。
    比如下面是我的一个jinja template tfcluster_template.yaml.jinja,

    {%- set name = "imagenet" -%}{%- set worker_replicas = 3 -%}{%- set ps_replicas = 2 -%}{%- set script = "http://xxx.xx.xx.xxx:80/imagenet/imagenet.py" -%}{%- set image = "tensorflow/tensorflow:1.3.0" -%}{%- set data_dir = "/data" -%}{%- set log_dir = "/log" -%}{%- set port = 2222 -%}{%- set replicas = {"worker": worker_replicas, "ps": ps_replicas} -%}
    
    	{%- macro worker_hosts() -%}{%- for i in range(worker_replicas) -%}{%- if not loop.first -%},{%- endif -%}{{ name }}-worker-{{ i }}:{{ port }}
    	  {%- endfor -%}{%- endmacro -%}{%- macro ps_hosts() -%}{%- for i in range(ps_replicas) -%}{%- if not loop.first -%},{%- endif -%}{{ name }}-ps-{{ i }}:{{ port }}
    	  {%- endfor -%}{%- endmacro -%}{%- for job in ["worker", "ps"] -%}{%- for i in range(replicas[job]) -%}
    	kind: Service
    	apiVersion: v1
    	metadata:
    	  name: {{ name }}-{{ job }}-{{ i }}
    	spec:
    	  selector:
    	    name: {{ name }}
    	    job: {{ job }}
    	    task: "{{ i }}"
    	  ports:
    	  - port: {{ port }}
    	    targetPort: 2222
    	{% if job == "worker" %}
    	---
    	kind: Job
    	apiVersion: batch/v1
    	metadata:
    	  name: {{ name }}-{{ job }}-{{ i }}
    	spec:
    	  replicas: 1
    	  template:
    	    metadata:
    	      labels:
    	        name: {{ name }}
    	        job: {{ job }}
    	        task: "{{ i }}"
    	    spec:
    	      containers:
    	      - name: {{ name }}-{{ job }}-{{ i }}
    	        image: {{ image }}
    	        ports:
    	        - containerPort: 2222
    	        command: ["/bin/sh", "-c"]
    	        args:["
    	            curl {{ script }} -o /opt/{{ name }}.py;
    	            python /opt/{{ name }}.py \
    	                   --ps_hosts={{ ps_hosts() }} \
    	                   --worker_hosts={{ worker_hosts() }} \
    	                   --job_name={{ job }} \
    	                   --task_index={{ i }} \
    	                   --log_path={{ log_dir }} \
    	                   --data_dir={{ data_dir }} ;"]
    	        volumeMounts: 
    	        - name: data
    	          mountPath: {{ data_dir }}
    	        - name: log
    	          mountPath: {{ log_dir }}
    	      restartPolicy: Never
    	      volumes:
    	        - name: data
    	          persistentVolumeClaim:
    	            claimName: {{ name }}-data-pvc
    	        - name: log
    	          persistentVolumeClaim:
    	            claimName: {{ name }}-log-pvc 
    	{% endif %}{% if job == "ps" %}
    	---
    	kind: Deployment
    	apiVersion: extensions/v1beta1
    	metadata:
    	  name: {{ name }}-{{ job }}-{{ i }}
    	spec:
    	  replicas: 1
    	  template:
    	    metadata:
    	      labels:
    	        name: {{ name }}
    	        job: {{ job }}
    	        task: "{{ i }}"
    	    spec:
    	      containers:
    	      - name: {{ name }}-{{ job }}-{{ i }}
    	        image: {{ image }}
    	        ports:
    	        - containerPort: 2222
    	        command: ["/bin/sh", "-c"]
    	        args:["
    	            curl {{ script }} -o /opt/{{ name }}.py;
    	            python /opt/{{ name }}.py \
    	                   --ps_hosts={{ ps_hosts() }} \
    	                   --worker_hosts={{ worker_hosts() }} \
    	                   --job_name={{ job }} \
    	                   --task_index={{ i }} \
    	                   --log_path={{ log_dir }} ;"]
    	        volumeMounts: 
    	        - name: log
    	          mountPath: {{ log_dir }}
    	      restartPolicy: Never
    	      volumes:
    	        - name: log
    	          persistentVolumeClaim:
    	            claimName: {{ name }}-log-pvc
    	{% endif %}
    	---
    	{% endfor %}{%- endfor -%}
    
    	apiVersion: v1
    	kind: PersistentVolumeClaim
    	metadata:
    	 name: {{ name }}-log-pvc
    	 annotations:
    	   volume.beta.kubernetes.io/storage-class: glusterfs
    	spec:
    	 accessModes:
    	  - ReadWriteMany
    	 resources:
    	   requests:
    	     storage: 10Gi
    	---
    	apiVersion: v1
    	kind: PersistentVolumeClaim
    	metadata:
    	 name: {{ name }}-data-pvc
    	 annotations:
    	   volume.beta.kubernetes.io/storage-class: glusterfs
    	spec:
    	 accessModes:
    	  - ReadWriteMany
    	 resources:
    	   requests:
    	     storage: 10Gi
    	---
    

    然后执行python render_template.py tfcluster_template.yaml.jinja | kubectl apply -f -完成对应的Between-Graph TensorFlow Cluster的创建和启动。

Summary

TensorFlow和Kubernetes分别作为深度学习和容器编排领域的王者,两者的合理整合可以将释放Distributed TensorFlow的能力,本文只是我对TensorFlow on Kubernetes的浅尝,未来还有很多工作需要做,比如给某些算法定制特殊的调度策略、网络IO性能调优、在DevOps上开发TaaS,提升易用性、TensorFlow Serving的快速部署等等,欢迎对这方面有浓厚兴趣的同学加我微信xidianwangtao交流。

 

 

https://my.oschina.net/jxcdwangtao/blog/1544050

分享到:
评论

相关推荐

    浅尝多媒体作品.ppt

    浅尝多媒体作品.ppt该文档详细且完整,值得借鉴下载使用,欢迎下载使用,有问题可以第一时间联系作者~

    Java 窗体对象浅尝

    Java 窗体对象浅尝,主要探讨的是如何在Java编程中使用Swing库来创建和管理用户界面,特别是窗体对象。Swing是Java的一个重要组件,它提供了丰富的图形用户界面(GUI)构建工具,比早期的AWT(Abstract Window ...

    Struts Validation框架浅尝

    ### Struts Validation框架浅尝 #### Struts Validation框架概述 Struts Validation框架是Apache Struts框架的一个重要组成部分,主要用于在Web应用中实现表单验证功能。通过使用该框架,开发者可以方便地对用户...

    第三方物流资源整合研究浅尝.doc

    【第三方物流资源整合研究浅尝】 第三方物流(3PL)是指企业将物流业务外包给专业的物流公司,以便自身专注于核心业务的经营。随着全球经济一体化,特别是中国加入世界贸易组织(WTO),国内物流市场面临着国内外...

    论文浅尝 # ICLR 2020 - 一文全览知识图谱研究

    ICLR(International Conference on Learning Representations)是机器学习领域最重要的会议之一,而2020年的ICLR吸引了大量研究者关注知识图谱相关的研究。以下是基于ICLR2020上知识图谱相关论文的五个主要研究方向...

    浅尝Spring注解开发_AOP原理及完整过程分析(源码).doc

    《浅尝Spring注解开发_AOP原理及完整过程分析(源码)》 Spring框架的注解开发在现代Java应用中扮演着至关重要的角色,尤其是其面向切面编程(AOP)特性,使得代码更加模块化,提高了可维护性和可重用性。本文将...

    多媒体教学初中物理的浅尝.doc

    【多媒体教学在初中物理教育中的应用】 随着信息技术的飞速发展,多媒体计算机已经逐渐成为现代教育的重要工具,尤其是在初中物理教学中,它的引入为教学带来了前所未有的变革。多媒体教学不仅提升了课堂信息量,...

    CAI在物理教学中的浅尝.doc

    计算机辅助教学(Computer Assisted Instruction,简称CAI)在物理教学中的应用,为解决传统教学中的难题提供了新的可能。物理学是一门需要深入理解和直观感受的学科,许多物理现象因为其短暂、微小、危险或者需要...

    浅尝Spring注解开发_Bean生命周期及执行过程.doc

    ingBean 和 DisposableBean 接口 当不使用注解而是通过实现接口的方式来控制 Bean 的生命周期时,可以实现 InitializingBean 和 DisposableBean 接口。这两个接口由 Spring 提供,它们包含两个方法: ...

    基于翻转课堂的DSP原理及应用教学改革浅尝.docx

    ### 基于翻转课堂的DSP原理及应用教学改革 #### 一、翻转课堂的概念及优势 翻转课堂是一种新型的教学模式,它颠覆了传统课堂中的教学流程,即教师不再单纯地在课堂上讲授新知识,而是让学生通过预习材料(如视频...

    VS2005入门视频教程-093.浅尝存储过程.rar

    本系列教程的课程安排参考了多本.net 1.1以及在目前的2.0新书的基础上认真编订。不敢夸口本系列多了不起,但至少敢保证你看完本系列,再做完每个小结的测试,你入门是绝对没有问题的!做一个简单的网站是绝对可以的!...

    以圆桌骑士为例浅尝HTML5游戏开发

    随着XHTML的逐渐式微,Chrome,Safari,FireFox,Opera等现代浏览器正在积极完善HTML5实现,IE9也加入到标准的行列并将在今年上半年发布正式版,HTML5时代来临了。...随着浏览器对canvas的普遍支持,利用canvas实现的...

    VSTS2010LoadTest性能测试浅尝

    VSTSTest因为工作需要,近期体验了VSTS2010Beta1中提供的负载测试功能。将会在后面的几篇博文中分享一些使用的心得。其实VisualStudioTeamSystemTest版本从version2005起就为用户提供了负载测试功能。...

    浙江鸭2018届高考生物专题训练25浅尝现代生物技术

    现代生物技术在生物学领域中扮演着重要的角色,尤其在植物繁殖和遗传改良方面。本专题训练主要关注现代生物技术在高考生物学科中的应用,通过选择题和非选择题的形式,帮助学生理解和掌握相关知识。...

    Restful Fast Request插件逆向

    本资源类似于 Postman 的 IDEA 插件Restful Fast Request,在IDEA安装该插件后,找到插件安装目录,【C:\\Users\\Administrator\\AppData\\Roaming\\JetBrains\\IntelliJIdea2021.3\\plugins\\Restful Fast Request ...

    浙江鸭2019高考生物二轮复习第八部分生物技术实践专题训练21生物技术在食品加工中的应用浅尝现代生物技术

    本资料主要涵盖了生物技术在食品加工中的应用,特别是针对高考生物二轮复习的专题训练,主要涉及的内容包括植物组织培养、发酵技术以及微生物在食品制作中的应用。 在植物组织培养方面,提到了菊花茎的切段在发芽...

    2013年高考生物二轮专题突破总复习 第40讲 浅尝现代生物技术随堂自测(含解析) 新人教版选修1

    【知识点详解】 1. 植物组织培养技术: - 植物组织培养是一种在无菌条件下,通过利用植物细胞全能性的繁殖技术。它主要用于繁殖名贵经济作物、珍稀濒危植物等。 - 在实际操作中,为了防止污染,植物组织需先进行...

    深入理解Linux修改hostname(推荐)

    技术活,切勿浅尝则止! 实验环境:Red Hat Enterprise Linux Server release 5.7 (Tikanga) ,其它版本Linux可能有所不同。请以实际环境为准。 其实我多次修改过hostname,一般只需要修改 /etc/hosts 和 /etc/...

Global site tag (gtag.js) - Google Analytics