3 系统架构

  1. 系统整体组成:Tensorflow的系统结构以C API为界,将整个系统分为前端和后端两个子系统:
  • 前端构造计算图
  • 后端执行计算图,可再细分为:
    • 运行时:提供本地模式和分布式模式
    • 计算层:由kernal函数组成
    • 通信层:基于gRPC实现组件间的数据交换,并能够在支持IB网络的节点间实现RDMA通信
    • 设备层:计算设备是OP执行的主要载体,TensorFlow支持多种异构的计算设备类型

2. 从图操作的角度看,TensorFlow执行步骤包括计算图的构造、编排、及其运行:

  • 表达图:构造计算图,但不执行(前端)
  • 编排图:将计算图的节点以最佳的执行方案部署在集群中各个计算设备上(运行时)
  • 运行图:按照拓扑排序执行图中的节点,并启动每个OP的Kernel计算(计算层、通信层、设备层)

3. 系统中重要部分(Client、Master、Worker)

  • Client:前端系统的主要组成部分,Client基于TensorFlow的编程接口,负责构造计算图。
  • Master负责的流程(接收并处理图):
    • Client执行Session.run时,传递整个计算图(Full Graph)给后端的Master
    • Master通过Session.run中的fetches、feeds参数根据依赖关系将Full Graph剪枝为小的依赖子图(Client Graph)
    • Master根据任务名称将Client Graph分为多个Graph Partition(SplitByTask),每个Graph Partition被注册到相应的Worker上(任务和Worker一一对应)
    • Master通知所有Worker启动相应Graph Partition并发执行
  • Worker负责的流程(再次处理图并执行图):
    • 处理来自Master的请求(图执行命令)
    • 对注册的Graph Partition根据本地设备集二次分裂(SplitByDevice),其中每个计算设备对应一个Graph Partition(是注册的Graph Partition中更小的Partition),并通知各个计算设备并发执行这个更小的Graph Partition(计算根据图中节点之间的依赖关系执行拓扑排序算法)
    • 按照拓扑排序算法在某个计算设备上执行本地子图,并调度OP的Kernel实现
    • 协同任务之间的数据通信(交换OP运算的结果)
      • 设备间Send/Recv(主要用于本地的数据交换):

        • 本地CPU与GPU之间,使用cudaMemcpyAsync实现异步拷贝
        • 本地GPU之间,使用端到端的DMA操作,避免主机端CPU的拷贝
      • 任务间通信(分布式运行时,Send/Recv节点通过GrpcRemoteRendezvous完成数据交换):
        • gRPC over TCP
        • RDMA over Converged Ethernet
  • Kernal:Kernel是OP在某种硬件设备的特定实现,它负责执行OP的具体运算,大多数Kernel基于Eigen::Tensor实现。Eigen::Tensor是一个使用C++模板技术

4. 图控制(实例解释3.3中的内容)

  • 组建集群

    • 假设一个分布式环境:1PS+1Worker,将其划分为两个任务:

      • ps0:使用/job:ps/task:0标记,负责模型参数的存储和更新
      • worker0:/job:worker/task:0标记,负责模型的训练
  • 图构造:Client构建了一个简单的计算图
  • 图执行:Client创建Session实例并调用Session.run将计算图传递给Master。Master在执行图计算之前会实施一系列优化技术,例如公共表达式消除,常量折叠等。最后,Master负责任务之间的协同,执行优化后的计算图。
  • 图分裂:Master将模型参数相关的OP划分为一组,并放置在ps0任务上;其他OP划分为另外一组,放置在worker0任务上执行
  • 子图注册:在图分裂过程中,如果计算图的边跨越节点或设备,Master将该边实施分裂,在两个节点或设备之间插入Send和Recv节点(Send和Recv节点是特殊OP,仅用于数据的通信,没有数据计算逻辑),最后Master通过调用RegisterGraph接口,将子图注册给相应的Worker上,并由相应的Worker负责执行运算。
  • 子图运算:Master通过调用RunGraph接口,通知所有Worker执行子图运算。其中,Worker之间可以通过调用RecvTensor接口,完成数据的交换

5. 会话管理(保障Client与Master之间的消息传递,执行图控制的操作)

  • 创建会话

    • Client首次执行tf.Session.run时,会将整个图序列化后,通过gRPC发送CreateSessionRequest消息,将图传递给Master
    • Master创建一个MasterSession实例,并用全局唯一的handle标识,最终通过CreateSessionResponse返回给Client
  • 迭代运行

    • Clent->Master。Client会启动迭代执行的过程,并称每次迭代为一次Step。此时,Client发送RunStepRequest消息给Master,消息携带handle标识,用于Master索引相应的MasterSession实例
    • Master图分裂。Master收到RunStepRequest消息后,Full Graph->Client Graph->Partition Graph->Master向Worker发送RegisterGraphRequest消息将Partition Graph注册到各个Worker节点上
    • Worker图分裂。当Worker收到RegisterGraphRequest消息后,再次实施分裂操作,最终按照设备将图划分为多个子图片段
    • 注册子图。当Worker完成子图注册后,通过返回RegisterGraphReponse消息,并携带graph_handle标识。这是因为Worker 可以并发注册并运行多个子图,每个子图使用graph_handle唯一标识。Master完成子图注册后通过发送RunGraphRequest消息给Worker并发执行所有子图,消息中携带(session_handle,graph_handle,step_id)三元组的标识信息,用于Worker索引相应的子图
    • 子图节点拓扑排序。Worker收到消息RunGraphRequest消息后,Worker根据graph_handle索引相应的子图。每个子图放置在单独的Executor中执行,Executor将按照拓扑排序算法完成子图片段的计算。
  • 数据交换

    • 设备间通信通过Send/Recv节点
    • Worker间通信涉及进程间通信,此时,需要通过接收端主动发送RecvTensorRequest消息到发送方,再从发送方的信箱取出对应的Tensor,并通过RecvTensorResponse返回
  • 关闭会话:计算完成后,Client向Master发送CloseSessionReq消息。Master收到消息后,开始释放MasterSession所持有的所有资源

4 C API:分水岭(前后端之间的通道的实现)

  1. 科普
  • Bazel:高级构建语言Bazel使用一种抽象的、人易于理解的、语义级别的高级语言来描述项目的构建属性。免于将单个调用编写到编译器和链接器等的复杂性
  • Swig:SWIG是一种简化脚本语言与C/C++接口的开发工具。简而言之,SWIG是一个通过包装和编译C语言程序来达到与脚本语言通讯目的的工具

2. Swig

  • TensorFlow使用Bazel的构建工具,在系统编译之前启动Swig的代码生成过程,通过tensorflow.i自动生成了两个适配(Wrapper) 文件:

    • pywrap_tensorflow_internal.py——负责对接上层Python调用:该模块首次被导入时,自动地加载_pywrap_tensorflow_internal.so的动态链接库;其中,_pywrap_tensorflow_internal.so包含了整个TensorFlow运行时的所有符号
    • http://pywrap_tensorflow_internal.cc——负责对接下层C API调用:该模块实现时,静态注册了一个函数符号表,实现了Python函数名到C函数名的二元关系。在运行时,按照Python的函数名称,匹配找到对应的C函数实现,最终实现Python到c_api.c具体实现的调用关系
  • Bazel生成规则定义于//tensorflow/python:pywrap_tensorflow_internal,如下图所示

3. 会话生命周期——包括会话的创建,创建计算图,扩展计算图,执行计算图,关闭会话,销毁会话六个过程,在前后端表现为两套相兼容的接口实现

  • Python前端的Session生命周期,下图为生命周期

    • 创建Session,tf.Session(target)
    • 迭代执行sess.run(fetchs,feed_dict)
      • sess._extend_graph(graph)
      • sess.TF_Run(feeds,fetches,targets)
    • 关闭Session,sess.close()
    • 销毁Session,sess.__del__
  • C++后端的Session生命周期,下图为生命周期和本地模型的DirectSession实例

    • 根据target多态创建Session
    • Session.Create(graph):有且仅有一次
    • Session.Extend(graph):零次或多次
    • 迭代执行Session.Run(inputs,outputs,targets)
    • 关闭Session.Close
    • 销毁Session对象

4. 会话周期各部分内容展开(展开4.3中的内容,从代码层面分析)

  • 创建会话

    • 过程:从Python前端为起点,通过Swig自动生成的Python-C++的包装器,并以此为媒介,实现了Python到TensorFlow的C API的调用
  • 编程接口(Python调用)

    • 创建了一个Session实例,调用父类BaseSession的构造函数,进而调用BaseSession的构造函数中pywrap_tensorflow模块中的函数(Python代码)
  • Session类构造函数中graph参数的定义如下图。ScopedTFGraph是对TF_Graph的包装器,完成类似于C++的RAII的工作机制。而TF_Graph持有 ternsorflow::Graph实例。其中,self._graph._c_graph返回一个TF_Graph实例,后者通过C API创建的图实例(Python代码)
  • 图实例传递如下(上面代码对应图中Python部分):
  • Python包装器:在pywrap_tensorflow模块中,通过_pywrap_tensorflow_internal的转发实现从Python到动态连接库_pywrap_tensorflow_internal.so的函数调用(对接上层Python调用,包含了整个TensorFlow运行时的所有符号)
  • C++包装器:在http://pywrap_tensorflow_internal.cc实现中,通过函数调用的符号表实现Python到C++的映射。_wrap_TF_NewSession/wrap_TF_NewDeprecatedSession将分别调用c_api.h对其开放的API接口:TF_NewSession/TF_NewDeprecatedSession。也就是说,自动生成的http://pywrap_tensorflow_internal.cc仅仅负责Python函数到C/C++函数调用的转发,最终将调用底层C系统向上提供的API接口
  • C API:c_api.h是TensorFlow的后端执行系统面向前端开放的公共API接口,实现采用了引用计数的技术,实现图实例在多个Session实例中共享
  • 后端系统(C API的底层C++实现):NewSession将根据前端传递的target,使用SessionFactory多态创建不同类型的tensorflow::Session实例(工厂方法)

    • SessionOptions中target为空字符串 (默认的),则创建DirectSession实例
    • SessionOptions中target以grpc://开头,则创建GrpcSession实例,启动基于RPC的分布式运行模式
  • 创建/扩展图

    • 过程:在既有的接口实现中,需要将图构造期构造好的图序列化,并传递给后端C++系统。而在新的接口实现中,无需实现图的创建或扩展

      • 新的接口:创建OP时,节点实时添加至后端C++系统的图实例中,而不像既有接口每次调用sess.run后在原先图实例的基础上再添加节点
      • 既有接口:Python前端将迭代调用Session.run接口,将构造好的计算图,以GraphDef的形式发送给C++后端。其中,前端每次调用Session.run接口时,都会试图将新增节点的计算图发送给后端系统,以便将新增节点的计算图Extend到原来的计算图中。特殊地,在首次调用Session.run时,将发送整个计算图给后端系统。后端系统首次调用Session.Extend时,转调Session.Create。以后,后端系统每次调用Session.Extend时将真正执行Extend的语义,将新增的计算图的节点追加至原来的计算图中
  • 编程接口

    • 在既有的接口实现中,通过_extend_graph实现图实例的扩展
  • 在首次调用self._extend_graph时,或者有新的节点被添加至计算图中时,对计算图GraphDef实施序列化操作,最终触发tf_session.TF_ExtendGraph的调用
  • Python包装器
  • C++包装器
  • C API:TF_ExtendGraph是C API对接上层编程环境的接口。首先,它完成计算图GraphDef的反序列化,最终调用tensorflow::Session的Extend接口
  • 后端系统:Create表示在当前的tensorflow::Session实例上注册计算图,如果要注册新的计算图,需要关闭该tensorflow::Session对象。Extend表示在tensorflow::Session实例上已注册的计算图上追加节点。Extend 首次执行时,等价于Create的语义。实现如首次扩展图GrpcSession所示:若引用Master的handle不为空则执行Extend,否则执行Create,建立与Master的连接并持有MasterSession的handle
  • 迭代运行

    • 过程:Python前端Session.run实现将fetches,feed_dict传递给后端系统,后端系统调用Session.Run接口
  • 编程接口:当Client调用Session.run时,最终会调用pywrap_tensorflow_internal模块中的函数
  • Python包装器
  • C++包装器
  • C API:在既有的接口中,TF_Run是C API对接上层编程环境的接口。首先,它完成输入数据从C到C++的格式转换,并启动后台的tensorflow::Session的执行过程。当执行完成后,再将outputs的输出数据从C++到C的格式转换。TF_SessionRun类似
    • 后端系统

      • 输入包括:

        • options:Session的运行配置参数
        • inputs:输入Tensor的名字列表
        • output_names:输出Tensor的名字列表
        • targets:无输出,待执行的OP的名字列表
      • 输出包括
        • outputs:输出的Tensor列表,outputs列表与输入的output_names一一对应
        • run_metadata:运行时元数据的收集器
  • 关闭会话
    • 过程:当计算图执行完毕后,需要关闭tf.Session,以便释放后端的系统资源,包括队列,IO等
  • 编程接口:当Client调用Session.close时,最终会调用pywrap_tensorflow模块中的函数:TF_CloseDeprecatedSession
  • Python包装器
  • C++包装器
  • C API:TF_CloseSession/TF_CloseDeprecatedSession直接完成tensorflow::Session的关闭操作
  • 后端系统:Session(C++)在运行时其动态类型,将多态地调用相应的子类实现
  • 销毁会话

    • 过程:当tf.Session不在被使用,由Python的GC释放。Client调用Session.__del__后,将启动后台tensorflow::Session对象的析构过程
  • 编程接口:Client调用Session.__del__时,先调用Session.close,再调用pywrap_tensorflow模块中的TF_DeleteSession/TF_DeleteDeprecatedSession
  • Python包装器
  • C++包装器
  • C API:TF_DeleteDeprecatedSession直接完成tensorflow::Session对象的释放。而新的接口TF_DeleteSession实现中,当需要删除tensorflow::Session实例时,相应的图实例的计数器减1。当计数器为0时,则删除该图实例;否则,不删除该图实例
  • 后端系统:tensorflow::Session在运行时其动态类型,多态地调用相应子类实现的析构函数

5. 性能调优(针对新实现的接口)

  • 共享图实例:一个Session只能运行一个图实例,如果一个Session要运行其他的图实例,必须先关掉Session,然后再将新的图实例注册到此Session中。但反过来,一个计算图可以运行在多个Session实例上。如果在Graph实例上维持Session的引用计数器,在Session创建时,在该图实例上增加1;在Session销毁时(不是关闭Session),在该图实例上减少1;当计数器为0时,则自动删除图实例(即:新接口加入了引用计数器)
  • 消除序列化

    • 遗留的接口实现中,前端构造图并将其序列化后,通过Session::Create或Session::Extend传递给后端。这本质是图实例的拷贝,具有很大的时延开销
  • 在新的接口实现中,可以去Create/Extend语义。在图的构造器,前端Python在构造每个OP时,直接通过C API将其追加至后端C++的图实例中,从而避免了图实例在前后端的序列化和反序列化的开销

tensorflow http调用_《TensorFlow 内核剖析》笔记——系统架构相关推荐

  1. 《深入理解Android 5 源代码》——第1章,第1.2节剖析Android系统架构

    本节书摘来自异步社区<深入理解Android 5 源代码>一书中的第1章,第1.2节剖析Android系统架构,作者 李骏,更多章节内容可以访问云栖社区"异步社区"公众 ...

  2. (软考笔记) —— 系统架构设计师 - UML建模与架构文档化

    文章目录 UML建模与架构文档化 UML 现状与发展 UML起源 UML 体系结构演变 UML 的应用与未来 UML基础 概述 用例和用例图 交互图 类图和对象图 状态和活动图 状态图 活动图 构件图 ...

  3. java布尔类型的调用_【Java学习笔记之八】JavaBean中布尔类型使用注意事项

    JavaBean是一个标准,遵循标准的Bean是一个带有属性和getters/setters方法的Java类. JavaBean的定义很简单,但是还有有一些地方需要注意,例如Bean中含有boolea ...

  4. 面具busybox模块_自定义内核及busybox系统定制

    查看本机硬件信息: 1.[root@localhost ~]# cat /proc/cpuinfo  #显示CPU信息# 2.[root@localhost ~]# lsusb   #显示USB接口信 ...

  5. java动态网站框架_大型网站动态应用系统架构

    动态应用,是相对于网站静态内容而言,是指以c/c++.php.Java.perl..net等服务器端语言开发的网络应用软件,比如论坛.网络相册.交友.BLOG等常见应用.动态应用系统通常与数据库系统. ...

  6. tensorflow怎样调用gpu_tensorflow基本用法(图,会话,tensor,变量等)

    使用 TensorFlow, 你必须明白 TensorFlow: 使用图 (graph) 来表示计算任务. 在被称之为 会话 (Session) 的上下文 (context) 中执行图. 使用 ten ...

  7. Tensorflow源码解析1 -- 内核架构和源码结构

    1 主流深度学习框架对比 当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层.比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android ...

  8. tensorflow怎样调用gpu_tensorflow / tensorflow-gpu / tensorflow-cpu区别?

    在tensorflow 1.x中, 环境 tensorflow==1.x tensorflow-gpu==1.x 只有CPU cpu运行 和tensorflow一样运行 有GPU且装Cuda和Cudn ...

  9. 06.图像识别与卷积神经网络------《Tensorflow实战Google深度学习框架》笔记

    一.图像识别问题简介及经典数据集 图像识别问题希望借助计算机程序来处理.分析和理解图片中的内容,使得计算机可以从图片中自动识别各种不同模式的目标和对象.图像识别问题作为人工智能的一个重要领域,在最近几 ...

最新文章

  1. 携程CEO称成功来自传统营销 B2C已经过时
  2. 10-Flink集群的高可用(搭建篇补充)
  3. linux中的五大查找命令---whereis,find,locate,which,type
  4. eureka hostname作用_SpringCloud基础教程(三)-Eureka进阶
  5. App设计灵感之十二组精美的外卖App设计案例
  6. Spring源码:IOC容器
  7. mysql如何管理空间_管理空间的mysql数据库
  8. MVVM(Knockout.js)的新尝试:多个Page,一个ViewModel
  9. 《IT蓝豹》PlayNewsStandDemo资讯类新闻客户端框架
  10. Mask-RCNN训练train_shapes.ipynb
  11. 【基础知识】【模块介绍】8位8段数码管(74HC595)【硬件部分】
  12. 国庆福利!384种故宫美色!Matlab中国风配色工具ColorPM
  13. Chartboost-x新鲜出炉: C++ Wrapper of Chartboost for Cocos2d-x
  14. HOG+SVM实现行人检测
  15. iOS开发 音频合成,改变音轨音量,改变背景音乐音量,音频剪辑
  16. jQuery 选择器 选取 class 为 intro 的 p 元素
  17. 为什么要申报绿色工厂?
  18. Firefox是如何将一手好牌打得稀烂的?
  19. 华为服务器不做阵列怎么进系统,服务器不做阵列能装系统
  20. 计算机网络信息中心研究生,计算机网络信息中心研究生招生常见问题答疑

热门文章

  1. java web 有哪些标签库_java web中jsp常用标签
  2. python27怎么使用_pygtk:glade的使用(针对python27的第一个例子)
  3. 内存压力测试软件_日常游戏,毫无压力,荣耀Magicbook 14锐龙版性能测试
  4. 谈一谈我对前端的学习路线及方法的一些心得
  5. Pi network到底怎么样?我们来深入剖析一下
  6. linux php 版本切换,linux更换PHP版本,多个PHP版本切换
  7. vue-cli使用说明
  8. Bootstrap中的圆角图片效果
  9. 文件指针创建失败!File *fp失败
  10. .NET core2.0 发布至IIS中