千家信息网

TensorFlow如何使用

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章主要讲解了"TensorFlow如何使用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"TensorFlow如何使用"吧!Distributed
千家信息网最后更新 2025年01月23日TensorFlow如何使用

这篇文章主要讲解了"TensorFlow如何使用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"TensorFlow如何使用"吧!


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中读取训练数据进行计算。

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

这个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来自动生成的,用户只要指定少量参数即可生成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的创建和启动。

感谢各位的阅读,以上就是"TensorFlow如何使用"的内容了,经过本文的学习后,相信大家对TensorFlow如何使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

训练 用户 集群 内容 算法 数据 方案 节点 服务 生成 分布式 容器 就是 状态 进程 问题 学习 运行 下图 参数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 ensembl数据库是干嘛的 java可以上传到其他服务器吗 越野车can总线网络技术要求 1数据库踏踏剧毒提痛哭流涕拒绝 网络安全实用教程第六章沈苏彬 聚航网络技术有限公司 如何加入北京通勤数据库 termux 服务器 公安网络安全执法工作培训班 校园网络安全隐患及其对策 六安数智未来电商软件开发 深入企业排查网络安全隐患 西湖论剑网络安全大会控场 数据库安全防火墙 服务器共享不了 如何选择软件开发商 广州嵌入式软件开发定制 陕西惠普服务器续保维护 达梦数据库2021年销量 数据库 表 同步数据 获取互联网科技信息的网站 幼儿园班级网络安全课活动记录 电脑网页数据库被破坏 如何加入北京通勤数据库 网络安全管理的六要素 程序外网直连数据库安全 深入企业排查网络安全隐患 陕西服务器机箱定制 青少年网络安全 主题班会 凯里网络安全系统多少钱
0