Update Automatic reference

This commit is contained in:
Eric_lai
2022-01-28 11:36:16 +08:00
parent 5ff00cf99e
commit ef354089a4
9 changed files with 49 additions and 38 deletions

View File

@@ -3,7 +3,7 @@
### 静态生成
静态图的生成与执行原理如图3.3.1所示,采用先编译后执行的方式,该模式将计算图的定义和执行进行分离。在静态图模式下使用前端语言定义模型形成完整的程序表达后,并不使用前端语言解释器进行执行,而是将前端描述的完整模型交给计算框架。框架在执行模型计算之前会首先对神经网络模型进行分析,获取网络层之间的连接拓扑关系以及参数变量设置、损失函数等信息,接着用一种特殊的静态数据结构来描述拓扑结构及其他神经网络模型组件,这种特殊的静态数据结构通常被称为静态计算图。静态计算图可以通过优化策略转换成等价的更加高效的结构。当进行模型训练或者推理过程时,静态计算图接收数据并通过相应硬件调度执行图中的算子来完成任务。
静态图的生成与执行原理如 :numref:`static`所示,采用先编译后执行的方式,该模式将计算图的定义和执行进行分离。在静态图模式下使用前端语言定义模型形成完整的程序表达后,并不使用前端语言解释器进行执行,而是将前端描述的完整模型交给计算框架。框架在执行模型计算之前会首先对神经网络模型进行分析,获取网络层之间的连接拓扑关系以及参数变量设置、损失函数等信息,接着用一种特殊的静态数据结构来描述拓扑结构及其他神经网络模型组件,这种特殊的静态数据结构通常被称为静态计算图。静态计算图可以通过优化策略转换成等价的更加高效的结构。当进行模型训练或者推理过程时,静态计算图接收数据并通过相应硬件调度执行图中的算子来完成任务。
![静态图生成与执行](../img/ch03/static.svg)
:width:`800px`
@@ -28,7 +28,7 @@ def model(X, flag):
:width:`800px`
:label:`staticgen`
经过编译后获取完整的计算图,能够根据全局信息完成图优化策略,进行编译优化形成与模型完全等价的静态图。编译器前端负责完成计算图与硬件无关的转换和优化,比如算子融合将网络中的两个或多个细粒度的算子融合为一个粗粒度算子,比如图3.3.2中将*add*算子与*relu*合并为一个操作,可节省中间计算结果的存储、读取等过程,降低框架底层算子调度的开销,从而提升执行性能和效率。编译器后端负责与硬件相关的计算图优化、代码指令生成和编译,优化手段包括硬件算子选择、内存分配、内存复用等,提高算子执行效率和内存利用效率,降低内存开销。编译器后端因此使用静态图模型运行往往能够获取更好的性能和更少的内存占用。在后续章节中将详细介绍更多编译器前端和编译器后端的优化策略。
经过编译后获取完整的计算图,能够根据全局信息完成图优化策略,进行编译优化形成与模型完全等价的静态图。编译器前端负责完成计算图与硬件无关的转换和优化,比如算子融合将网络中的两个或多个细粒度的算子融合为一个粗粒度算子,比如 :numref:`staticgen`中将*add*算子与*relu*合并为一个操作,可节省中间计算结果的存储、读取等过程,降低框架底层算子调度的开销,从而提升执行性能和效率。编译器后端负责与硬件相关的计算图优化、代码指令生成和编译,优化手段包括硬件算子选择、内存分配、内存复用等,提高算子执行效率和内存利用效率,降低内存开销。编译器后端因此使用静态图模型运行往往能够获取更好的性能和更少的内存占用。在后续章节中将详细介绍更多编译器前端和编译器后端的优化策略。
优化完成的计算图通过编译器后端根据计算硬件来生成适配的执行代码。在执行阶段,调用执行器接受输入数据,依据计算图调度算子执行训练或者推理任务。在训练任务调度算子执行时,由于在执行阶段已经编译获取模型整体结构,计算框架可以利用自动并行算法制定合理的模型切分与并行策略,进一步提高计算效率。
@@ -38,7 +38,7 @@ def model(X, flag):
### 动态生成
动态图原理如图3.3.3所示,采用解析式的执行方式,其核心特点是编译与执行同时发生。动态图采用前端语言自身的解释器对代码进行解析,利用计算框架本身的算子分发功能,算子会即刻执行并输出结果。动态图模式采用用户友好的命令式编程范式,使用前端语言构建神经网络模型更加简洁。
动态图原理如 :numref:`dynamic`所示,采用解析式的执行方式,其核心特点是编译与执行同时发生。动态图采用前端语言自身的解释器对代码进行解析,利用计算框架本身的算子分发功能,算子会即刻执行并输出结果。动态图模式采用用户友好的命令式编程范式,使用前端语言构建神经网络模型更加简洁。
![动态图原理](../img/ch03/dynamic.svg)
:width:`600px`
@@ -52,11 +52,11 @@ def model(X, flag):
:width:`700px`
:label:`dynamicgen`
图3.3.4中所示,神经网络前向计算按照模型声明定义的顺序进行执行。当模型接收输入数据$\boldsymbol{X}$后,计算框架开始动态生成图拓扑结构,添加输入节点并准备将数据传输给后续节点。模型中存在条件控制时,动态图模式下会即刻得到逻辑判断结果并确定数据流向,因此在图中假设判断结果为真的情况下,图结构中仅会添加关于张量$\boldsymbol{W1}$的*matmul*算子节点。按照代码制定的模型计算顺序与算子依赖关系,计算框架会依次添加*add*算子节点和*ReLU*算子节点。计算框架会在添加节点的同时完成算子分发计算并返回计算结果,同时做好准备向后续添加的节点传输数据。当模型再次进行前向计算时,动态生成的图结构则失效,并再次根据输入和控制条件生成新的图结构。相比于静态生成,可以发现动态生成的图结构并不能完整表示前端语言描述的模型结构,需要即时根据控制条件和数据流向产生图结构。由于计算框架无法通过动态生成获取完整的图结构,因此动态图模式下难以进行图结构优化以提高计算效率。
:numref:`dynamicgen`中所示,神经网络前向计算按照模型声明定义的顺序进行执行。当模型接收输入数据$\boldsymbol{X}$后,计算框架开始动态生成图拓扑结构,添加输入节点并准备将数据传输给后续节点。模型中存在条件控制时,动态图模式下会即刻得到逻辑判断结果并确定数据流向,因此在图中假设判断结果为真的情况下,图结构中仅会添加关于张量$\boldsymbol{W1}$的*matmul*算子节点。按照代码制定的模型计算顺序与算子依赖关系,计算框架会依次添加*add*算子节点和*ReLU*算子节点。计算框架会在添加节点的同时完成算子分发计算并返回计算结果,同时做好准备向后续添加的节点传输数据。当模型再次进行前向计算时,动态生成的图结构则失效,并再次根据输入和控制条件生成新的图结构。相比于静态生成,可以发现动态生成的图结构并不能完整表示前端语言描述的模型结构,需要即时根据控制条件和数据流向产生图结构。由于计算框架无法通过动态生成获取完整的图结构,因此动态图模式下难以进行图结构优化以提高计算效率。
在静态生成环节,由于已经获取完整的神经网络模型定义,因此可以同时构建出完整的前向计算图和反向计算图。而在动态生成中,由于边解析边执行的特性,反向梯度计算的构建随着前向计算调用而进行。在执行前向过程中,计算框架根据前向算子的调用信息,记录对应的反向算子信息以及参与梯度计算的张量信息。前向计算完毕之后,反向算子与张量信息随之完成记录,计算框架会根据前向动态图拓扑结构,将所有反向过程串联起来形成整体反向计算图。最终,将反向图在计算硬件上执行计算得到梯度用于参数更新。
对应于图3.3.4中,当调用到关于张量$\boldsymbol{W1}$的*matmul*算子节点时,框架会执行两个操作:调用*matmul*算子,计算关于输入$\boldsymbol{X}$和$\boldsymbol{W1}$的乘积结果,同时根据反向计算过程$\boldsymbol{Grad\_W1}=\boldsymbol{Grad\_Y}*\boldsymbol{X}$,记录下需要参与反向计算的算子和张量$\boldsymbol{X}$。计算框架依照算子调度顺序记录参与反向计算的算子和张量。当前向计算执行完毕,计算框架根据动态生成的前向计算图结构拓扑关系,利用记录的反向计算算子和张量动态生成反向计算图,最终完成神经网络模型的梯度计算和参数更新。
对应于 :numref:`dynamicgen`中,当调用到关于张量$\boldsymbol{W1}$的*matmul*算子节点时,框架会执行两个操作:调用*matmul*算子,计算关于输入$\boldsymbol{X}$和$\boldsymbol{W1}$的乘积结果,同时根据反向计算过程$\boldsymbol{Grad\_W1}=\boldsymbol{Grad\_Y}*\boldsymbol{X}$,记录下需要参与反向计算的算子和张量$\boldsymbol{X}$。计算框架依照算子调度顺序记录参与反向计算的算子和张量。当前向计算执行完毕,计算框架根据动态生成的前向计算图结构拓扑关系,利用记录的反向计算算子和张量动态生成反向计算图,最终完成神经网络模型的梯度计算和参数更新。
尽管动态生成中完整的网络结构在执行前是未知的,不能使用静态图中的图优化技术来提高计算执行性能。但其即刻算子调用与计算的能力,使得模型代码在运行的时候,每执行一句立即进行运算并会返回具体的值,方便开发者在模型构建优化过程中的进行错误分析、结果查看等调试工作,为研究和实验提供了高效的助力。
@@ -75,7 +75,7 @@ def model(X1, X2):
```
在静态生成过程中,计算框架获取完整的计算图可以分析出计算$\boldsymbol{Y_1}$和$\boldsymbol{Y_2}$的过程相对独立,可以将其进行自动并行计算,加快计算效率。而动态生成的过程中,若无手动配置并行策略,计算框架无法获取图结构不能分析出算子之间的独立性,则只能按照代码顺序执行。模型在输出结果之前执行了*add*和*relu*算子操作,在静态生成过程中利用计算图优化策略中的算子融合方法,可以将这两个算子融合为一个算子执行,这样减少了中间变量$\boldsymbol{Y}$的存储与读取过程,加快了计算效率,减少了内存占用。而动态生成过程则需要按照顺序执行*add*和*relu*两步操作,需要存储变量$\boldsymbol{Y}$。除此之外,由于静态生成能够同时分析重构出前向计算图和反向计算图,可以提前确定反向计算中需要保存的前向中间变量信息。而动态生成则在完成前向计算后才能构建出反向计算图,为了保证反向计算效率需要保存更多的前向计算中间变量信息,相比之下静态生成的过程更加节省内存占用。
为了方便读者对比,将静态图和动态图特性总结见表3.3.1
为了方便读者对比,将静态图和动态图特性总结见 :numref:`cmp_dynamic_static`
:静态图和动态图对比
@@ -105,7 +105,7 @@ def model(X1, X2):
动态图基于前端语言自身的解释器进行模型代码的解析执行。比如当python作为前端语言采取原生python边运行边解释的特性配合框架提供的数据处理/算子分发的功能计算,即可实现动态图的即时执行特性。而且静态图则采用计算框架自带的图编译器,对神经网络模型进行建图后,再调用图结构进行计算。动态图代码与静态图代码之间存在差异,不能直接使用静态图编译器,因此基于源码转换的方法需要将动态图代码转换为静态图代码描述。
**基于源码转换**的方式则能够改善基于追踪转换的缺陷。如图3.3.5中所示,基于源码转换的流程经历两个阶段。第一个阶段,对动态图模式下的代码扫描进行词法分析,通过词法分析器分析源代码中的所有字符,对代码进行分割并移除空白符、注释等,将所有的单词或字符都转化成符合规范的语法单元列表。接着进行语法分析即解析器,将得到的语法单元列表转换成树形式,并对语法进行检查避免错误。第二阶段,动态图转静态图的核心部分就是对抽象语法树进行转写,计算框架中对每一个需要转换的语法都预设有转换器,每一个转换器对语法树进行扫描改写,将动态图代码语法映射为静态图代码语法。其中最为重要的前端语言控制流,会在这一阶段分析转换为静态图接口进行实现。转写完毕之后,将新的语法树再还原回静态图代码,就可以使用静态生成执行。使用该方式可以避免基于追踪转换中控制流表达缺失的情况。
**基于源码转换**的方式则能够改善基于追踪转换的缺陷。如 :numref:`ast`中所示,基于源码转换的流程经历两个阶段。第一个阶段,对动态图模式下的代码扫描进行词法分析,通过词法分析器分析源代码中的所有字符,对代码进行分割并移除空白符、注释等,将所有的单词或字符都转化成符合规范的语法单元列表。接着进行语法分析即解析器,将得到的语法单元列表转换成树形式,并对语法进行检查避免错误。第二阶段,动态图转静态图的核心部分就是对抽象语法树进行转写,计算框架中对每一个需要转换的语法都预设有转换器,每一个转换器对语法树进行扫描改写,将动态图代码语法映射为静态图代码语法。其中最为重要的前端语言控制流,会在这一阶段分析转换为静态图接口进行实现。转写完毕之后,将新的语法树再还原回静态图代码,就可以使用静态生成执行。使用该方式可以避免基于追踪转换中控制流表达缺失的情况。
![基于源码转换流程](../img/ch03/ast.svg)
:width:`800px`
@@ -129,7 +129,7 @@ def model(X, flag):
```
代码中模型整体可以采用动态生成,而\@ms\_function可以使用基于源码转换的技术将模块*add_and_relu*的转化为静态图结构。与动态生成中代码执行相同,模型接受输入按照模型定义的计算顺序进行调度执行,并生成临时图结构,当执行语句*Y=add_and_relu(Y,b)* 时,计算框架会自动调用该模块静态生成的图结构执行计算。模块*add_and_relu* 可以利用静态图中的优化技术来提高计算性能,实现动态图和静态图的混合执行。此外,动静态转换的技术常用于模型部署阶段,动态图预测部署时除了需要已经训练完成的参数文件,还须提供最初的模型组网前端代码,这使得动态图部署受到局限性,部署硬件中往往难以提供支持前端语言执行环境。因此当使用动态图模式训练完成模型参数后,可以将整体网络结构转换为静态图格式,将神经网络模型和参数文件进行序列化保存,与前端代码完全解耦,扩大模型部署的硬件支持范围。
主流的计算框架TensorFlow、MindSpore等中均提供动静态相互转换与融合执行的技术我们将各框架中支持源码转换和追踪转换技术的接口梳理如下表3.3.2所示。
主流的计算框架TensorFlow、MindSpore等中均提供动静态相互转换与融合执行的技术我们将各框架中支持源码转换和追踪转换技术的接口梳理如 :numref:`dynamic_static_switch`所示。
:主流框架动态图转换静态图支持