TensorFlow架构与设计:概述

杨大海3 8年前
   <p><img src="https://simg.open-open.com/show/ebee4e3d4e7faa4d039591e61bbbc4f1.jpg"></p>    <h2>TensorFlow是什么?</h2>    <p>TensorFlow 基于数据流图,用于大规模分布式数值计算的开源框架。节点表示某种抽象的计算,边表示节点之间相互联系的张量。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4a67e12961d71d510c83c2aa35a8febb.gif"></p>    <p style="text-align: center;">计算图实例</p>    <p>TensorFlow 支持各种异构的平台,支持多 CPU/GPU ,服务器,移动设备,具有良好的跨平台的特性; TensorFlow 架构灵活,能够支持各种网络模型,具有良好的通用性;此外, TensorFlow 架构具有良好的可扩展性,对 OP 的扩展支持, Kernel 特化方面表现出众。</p>    <p>TensorFlow 最初由 Google 大脑的研究员和工程师开发出来,用于机器学习和神经网络方面的研究,于 2015.10 宣布开源,在众多深度学习框架中脱颖而出,在 Github 上获得了最多的 Star 量。</p>    <p>本文将阐述 TensorFlow 的系统架构,帮助读者加深理解 TensorFlow 的工作机理。</p>    <p>本文假设读者已经了解 TensorFlow 的基本编程模型,包括计算图, OP , Tensor , Session 等基本概念。</p>    <h2>系统概述</h2>    <p>TensorFlow 的系统结构以 C API 为界,将整个系统分为「前端」和「后端」两个子系统:</p>    <ul>     <li>前端系统:提供编程模型,负责构造计算图;</li>     <li>后端系统:提供运行时环境,负责执行计算图。</li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/ea49ee7dbfd03297abe2fe05b370a70e.png"></p>    <p style="text-align: center;">TensorFlow系统架构</p>    <p>如上图所示,重点关注系统中如下4个基本组件,它们是系统分布式运行机制的核心。</p>    <h3>Client</h3>    <p>Client 是前端系统的主要组成部分,它是一个支持多语言的编程环境。它提供基于计算图的编程模型,方便用户构造各种复杂的计算图,实现各种形式的模型设计。</p>    <p>Client 通过 Session 为桥梁,连接 TensorFlow 后端的「运行时」,并启动计算图的执行过程。</p>    <h3>Distributed Master</h3>    <p>在分布式的运行时环境中, Distributed Master 根据 Session.run 的 Fetching 参数,从计算图中反向遍历,找到所依赖的「最小子图」。</p>    <p>然后, Distributed Master 负责将该「子图」再次分裂为多个「子图片段」,以便在不同的进程和设备上运行这些「子图片段」。</p>    <p>最后, Distributed Master 将这些「子图片段」派发给 Work Service ;随后 Work Service 启动「子图片段」的执行过程。</p>    <h3>Worker Service</h3>    <p>对于每以个任务, TensorFlow 都将启动一个 Worker Service 。 Worker Service 将按照计算图中节点之间的依赖关系,根据当前的可用的硬件环境(GPU/CPU),调用 OP 的 Kernel 实现完成 OP 的运算(一种典型的多态实现技术)。</p>    <p>另外, Worker Service 还要负责将 OP 运算的结果发送到其他的 Work Service ;或者接受来自其他 Worker Service 发送给它的 OP 运算的结果。</p>    <h3>Kernel Implements</h3>    <p>Kernel 是 OP 在某种硬件设备的特定实现,它负责执行 OP 的运算。</p>    <h2>组件交互</h2>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/67c707a9f1341e4b596ab76152191a6d.png"></p>    <p style="text-align: center;">组件交互</p>    <p>如上图所示,假设存在两个任务:</p>    <ul>     <li>/job:ps/task:0 : 负责模型参数的存储和更新</li>     <li>/job:worker/task:0 : 负责模型的训练或推理</li>    </ul>    <p>接下来,我们将进一步抽丝剥茧,逐渐挖掘出 TensorFlow 计算图的运行机制。</p>    <h2>客户端</h2>    <p>Client 基于 TensorFlow 的编程接口,构造计算图。目前, TensorFlow 主流支持 Python 和 C++ 的编程接口,并对其他编程语言接口的支持日益完善。</p>    <p>此时, TensorFlow 并未执行任何计算。直至建立 Session 会话,并以 Session 为桥梁,建立 Client 与后端运行时的通道,将 Protobuf 格式的 GraphDef 发送至 Distributed Master 。</p>    <p>也就是说,当 Client 对 OP 结果进行求值时,将触发 Distributed Master 的计算图的执行过程。</p>    <p>如下图所示, Client 构建了一个简单计算图。它首先将 w 与 x 进行矩阵相乘,再与截距 b 按位相加,最后更新至 s 。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/8b52a77d5e37cf69f5a994dc1a8bc66c.png"></p>    <p style="text-align: center;">构造计算图</p>    <h2>Distributed Master</h2>    <p>在分布式的运行时环境中, Distributed Master 根据 Session.run 的 Fetching 参数,从计算图中反向遍历,找到所依赖的最小子图。</p>    <p>然后 Distributed Master 负责将该子图再次分裂为多个「子图片段」,以便在不同的进程和设备上运行这些「子图片段」。</p>    <p>最后, Distributed Master 将这些图片段派发给 Work Service 。随后 Work Service 启动「本地子图」的执行过程。</p>    <p>Distributed Master 将会缓存「子图片段」,以便后续执行过程重复使用这些「子图片段」,避免重复计算。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/db80cb9b6755ca0e2c24d9c9339a8736.png"></p>    <p style="text-align: center;">执行图计算</p>    <p>如上图所示, Distributed Master 开始执行计算子图。在执行之前, Distributed Master 会实施一系列优化技术,例如「公共表达式消除」,「常量折叠」等。随后, Distributed Master 负责任务集的协同,执行优化后的计算子图。</p>    <p>子图片段</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2d0ccff7ea00ff99dce06003819b1713.png"></p>    <p style="text-align: center;">子图片段</p>    <p>如上图所示,存在一种合理的「子图片段」划分算法。 Distributed Master 将模型参数相关的 OP 进行分组,并放置在 PS 任务上。其他 OP 则划分为另外一组,放置在 Worker 任务上执行。</p>    <p>SEND/RECV节点</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/b94ce40b806b11625b1765b2a3f8f7e1.png"></p>    <p style="text-align: center;">插入SEND/RECV节点</p>    <p>如上图所示,如果计算图的边被任务节点分割, Distributed Master 将负责将该边进行分裂,在两个分布式任务之间插入 SEND 和 RECV 节点,实现数据的传递。</p>    <p>随后, Distributed Master 将「子图片段」派发给相应的任务中执行,在 Worker Service 成为「本地子图」,它负责执行该子图的上的 OP 。</p>    <h2>Worker Service</h2>    <p>对于每个任务,都将存在相应的 Worker Service ,它主要负责如下3个方面的职责:</p>    <ul>     <li>处理来自 Master 的请求;</li>     <li>调度 OP 的 Kernel 实现,执行本地子图;</li>     <li>协同任务之间的数据通信。</li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/78fea420d7898d2fe40d5db8bc68fd32.png"></p>    <p style="text-align: center;">执行本地子图</p>    <p>Worker Service 派发 OP 到本地设备,执行 Kernel 的特定实现。它将尽最大可能地利用多 CPU/GPU 的处理能力,并发地执行 Kernel 实现。</p>    <p>另外, TensorFlow 根据设备类型,对于设备间的 SEND/RECV 节点进行特化实现:</p>    <ul>     <li>使用 cudaMemcpyAsync 的API实现本地 CPU 与 GPU 设备的数据传输;</li>     <li>对于本地的 GPU 之间则使用端到端的 DMA ,避免了跨 host CPU 昂贵的拷贝过程。</li>    </ul>    <p>对于任务之间的数据传递, TensorFlow 支持多协议,主要包括:</p>    <ul>     <li>gRPC over TCP</li>     <li>RDMA over Converged Ethernet</li>    </ul>    <h2>Kernel Implements</h2>    <p>TensorFlow 的运行时包含 200 多个标准的 OP ,包括数值计算,多维数组操作,控制流,状态管理等。每一个 OP 根据设备类型都会存在一个优化了的 Kernel 实现。在运行时,运行时根据本地设备的类型,为 OP 选择特定的 Kernel 实现,完成该 OP 的计算。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/9c64ba18fff07f241d856bdf876f95b2.png"></p>    <p style="text-align: center;">TensorFlow Core</p>    <p>其中,大多数 Kernel 基于 Eigen::Tensor 实现。 Eigen::Tensor 是一个使用 C++ 模板技术,为多核 CPU/GPU 生成高效的并发代码。但是, TensorFlow 也可以灵活地直接使用 cuDNN 实现更高效的 Kernel 。</p>    <p>此外, TensorFlow 实现了矢量化技术,使得在移动设备,及其满足高吞吐量,以数据为中心的应用需求,实现更高效的推理。</p>    <p>如果对于复合 OP 的子计算过程很难表示,或执行效率低下, TensorFlow 甚至支持更高效的 Kernle 实现的注册,其扩展性表现相当优越。</p>    <h2>技术栈</h2>    <p>最后,按照 TensorFlow 的软件层次,通过一张表格罗列 TensorFlow 的技术栈,以便更清晰地对上述内容做一个简单回顾。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/90ae990ce73dda27d100a1bd6a853e8a.png"></p>    <p style="text-align: center;">TensorFlow技术栈</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/a5574ebcdeab</p>    <p> </p>