智能计算系统 第五章 编程框架机理
智能计算系统 第五章 编程框架机理
5.1 Tensorflow 设计原则
高性能、易开发、可移植
高性能
- Tensorflow 中的算子,设计过程中就已经针对底层硬件架构进行了充分的优化
- 针对生成的计算图,Tensorflow 又提供了一系列的优化操作,以提升计算图的运行效率
- Tensorflow 调度器可以根据网络结构的特点,并发运行没有数据依赖的节点
易开发
- 针对现有的多种深度学习算法,提取了大量的共性运算,封装成算子
- 用户使用tensorflow进行算法开发时,能够直接调用这些算子,很方便的实现算法
可移植
- 可工作与各种类型的异构系统
- 对每个算子需提供在不同设备上的不同底层实现
- 用户程序可以在不同的硬件平台上执行
5.2 Tensorflow 计算图机制
计算图的自动求导
- 深度学习中通常采用梯度下降更新模型参数
- 对于复杂模型,手动计算梯度困难
- 大部分深度学习框架均需提供自动梯度计算功能
- 用户只需要描述前向计算的过程,由编程框架自动推导反向计算图,完成求导
常见求导方法
手动求导法
手动用链式法则求出梯度公式,代入数值得到梯度值
缺点
- 对大规模的深度学习算法,手动链式求导法则计算非常困难
- 需要手动编写梯度求解代码
- 每次修改算法模型,都需要修改对应的梯度求解方法
数值求导法
利用倒数的原始定义求解
优点
- 易操作
- 可对用户隐藏求导过程
缺点
- 计算量大,速度慢
- 可能引起舍入误差和截断误差
符号求导法
利用求导规则对表达式自动操作,从而获得倒数
缺点:表达式膨胀问题
自动求导法
介于数值求导和符号求导法的方法
计算图结构天然使用于自动求导
优点
- 灵活,可以隐藏求导过程
- 只对基本函数运行符号求导法,可以灵活结合编程语言的循环结构、条件结构等
tensorflow 中可注册函数的反向求导法
计算步骤
- 原始函数建立计算图,数据正向传播,计算出中间节点xi,并记录计算图中节点依赖关系
- 反向遍历计算图,计算输出对于每个节点的倒数
检查点机制
使用tf.train.Saver()来保存模型中的所有变量
恢复模型
使用 restore 函数
TensorFlow 中的控制流
- TensorFlow 中使用控制流算子来实现不同复杂控制流场景
- 引入少量简单基础操作,为多样的 Tensorflow 应用提供丰富的控制流表达
- 在 Tensorflow 中,每一个操作都会在一个执行帧中被执行,控制流操作负责创建和管理这些执行帧
计算图本地执行
计算图剪枝
得到本地运行的最小子图
- 为输入输出建立与外界交互
- 通过函数调用帧来解决输入输出值传递问题
- 在每个输入节点前插入arg节点,所有输入节点连接到Source节点上,并通过控制依赖边相连
- 在每个输出节点后面加入retval节点,所有输出节点连接到sink节点上,也通过依赖边相连,最终行成完整的计算图
- 去除与最终输出节点无关的节点和边
- 从输出节点进行BFS,删除没有接触到的节点和边
- 将每个连通图入度为0的节点通过控制依赖与source节点相连,出度为0的节点通过控制依赖边和sink节点相连
计算图分配
问题:多设备运行环境中,对计算图中每个节点如何分配计算设备
目标:保证计算的快速执行
对计算图中每个结点如何分配计算设备算法执行过程
- 从计算图起始点开始遍历
- 对于遍历中的每个结点,考虑其可行的设备集合
- 如果设备不提供实现特定操作的内核,则设备不可行
- 如果某个节点具有多个可行设备,则采用贪心算法,检查该节点在所有可行设备上完成的时间,将最快完成的设备分配给该节点
- 重复2-4直到遍历完成整个图
计算图优化
- tensorflow 中图的优化由 Grappler 模块来实现
- 通过图优化,可以根据不同的硬件结构调整计算调度策略,从而获得更快的计算速度和更高的硬件效率
- 也能减少推断过程中所需的峰值内存,从而运行更大的模型
常量折叠 ConstFold
有的常数节点可以被提前计算,用得到的结果生成新的节点来代替原来的常数节点
算数优化
公共子表达式删除、算术简化
布局优化
数据摆放方式的转换
重映射
- 算子融合,出现频率较高的子图用一个单独的算子来替代
好处 - 消除子图调度开销
- 计算conv2d+biasAdd时,conv2d的数据处理是分块进行的,融合后的biasAdd也可以在片上存储里进行,降低访存开销
计算图切分和设备通信
- 完成每个节点的设备分配后,将整个计算图按照所分配设备分成若干子图,每个设备一张子图
容错机制
- 检查send和recv节点传输的正确性
- 检查到错误时,计算图执行过程会停止并重启
- 保存中间状态,用于立即恢复到出错前状态
5.3 Tensorflow 系统实现
整体架构
- 面向各个语言的语言包
- C/C++ API
- 后端代码
- session
- 图的优化和切分
- 算子库
计算图执行模块
- session 是用户和 tensorflow 运行时的接口,session 接收到输入数据时,便可开始运行
- 每个设备会有一个执行器,负责本设备上子计算图的执行
- run 函数是 session 执行的核心逻辑,在其中完成计算图的执行,包括传参、运行和返回
执行器逻辑
- 执行流:一个能够存储计算任务的队列
- 流间任务可以并行执行,流内任务穿行执行
设备抽象和管理
- tensorflow将设备分成本地设备和远程设备
- 使用注册机制来管理设备,每个设备负责一个子图运算,可以通过注册接口支持自定义设备
网络和通信
- tensorflow设备间通信由send和receive节点进行,使用rendezvous机制
算子实现
- tensorflow的基本单元,OpKernel 是算子的特定执行,依赖于底层硬件
- tensorflow 通过注册机制来支持不同的算子和相应的OpKernel函数
5.4 驱动范例
构建VGG网络
就像搭积木一样
内部构图逻辑
加载模型执行预测
5.5 编程框架对比
pytorch
- 小而灵活
- 支持python和c++
- 学术界主要用
MXNet
- 针对效率和灵活性设计
- 支持声明式编程以及命令式编程
- 支持R Julia Go等语言
Caffe
- 最早出现的框架
- 缺少灵活性、扩展性和复用性
- 不再维护更新
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment
GiscusGitalk