diff --git a/doc/fluid/advanced_usage/design_idea/fluid_design_idea.md b/doc/fluid/advanced_usage/design_idea/fluid_design_idea.md index bb344dbb890da6262d3fa9d455717e4e4c54c06a..fe3a9d2c22202430f0aab2295ff14e661637054a 100644 --- a/doc/fluid/advanced_usage/design_idea/fluid_design_idea.md +++ b/doc/fluid/advanced_usage/design_idea/fluid_design_idea.md @@ -2,53 +2,51 @@ ## 简介 -本篇文档主要介绍Fluid底层的设计思想,帮助用户更好的理解框架运作过程。 +本篇文档主要介绍飞桨(PaddlePaddle,以下简称Paddle)底层的设计思想,帮助用户更好的理解框架运作过程。 阅读本文档,您将了解: -- Fluid 内部的执行流程 +- Paddle 内部的执行流程 - Program 如何描述模型 - Executor 如何执行运算 -## 1. Fluid内部执行流程 +## 1. Paddle内部执行流程 -Fluid使用一种编译器式的执行流程,分为编译时和运行时两个部分,具体包括:编译器定义 Program ,创建Executor 运行 Program 。 +Paddle使用一种编译器式的执行流程,分为编译时和运行时两个部分,具体包括:编译器定义 Program ,创建Executor 运行 Program 。 本地训练任务执行流程图如下所示:
- 1. 编译时,用户编写一段python程序,通过调用 Fluid 提供的算子,向一段 Program 中添加变量(Tensor)以及对变量的操作(Operators 或者 Layers)。用户只需要描述核心的前向计算,不需要关心反向计算、分布式下以及异构设备下如何计算。 - - 2. 原始的 Program 在平台内部转换为中间描述语言: `ProgramDesc`。 - - 3. 编译期最重要的一个功能模块是 `Transpiler`。`Transpiler` 接受一段 `ProgramDesc` ,输出一段变化后的 `ProgramDesc` ,作为后端 `Executor` 最终需要执行的 Fluid Program - - 4. 后端 Executor 接受 Transpiler 输出的这段 Program ,依次执行其中的 Operator(可以类比为程序语言中的指令),在执行过程中会为 Operator 创建所需的输入输出并进行管理。 + 1. 编译时,用户编写一段python程序,通过调用 Paddle 提供的算子,向一段 Program 中添加变量(Tensor)以及对变量的操作(Operators 或者 Layers)。用户只需要描述核心的前向计算,不需要关心反向计算、分布式下以及异构设备下如何计算。 + 2. 原始的 Program 在框架内部转换为中间描述语言: `ProgramDesc`。 + 3. `Transpiler` 接受一段 `ProgramDesc` ,输出一段变化后的 `ProgramDesc` ,作为后端 `Executor` 最终需要执行的 Program 。 `Transpiler` 并非必需步骤。 + + 4. 执行 `ProgramDesc` 中定义的 Operator(可以类比为程序语言中的指令),在执行过程中会为 Operator 创建所需的输入输出并进行管理。 ## 2. Program设计思想 -用户完成网络定义后,一段 Fluid 程序中通常存在 2 段 Program: +用户完成网络定义后,一段 Paddle 程序中通常存在 2 个 Program: - 1. fluid.default_startup_program:定义了创建模型参数,输入输出,以及模型中可学习参数的初始化等各种操作 + 1. fluid.default_startup_program:定义了模型参数初始化、优化器参数初始化、reader初始化等各种操作。 - default_startup_program 可以由框架自动生成,使用时无需显示地创建 + default_startup_program 可以由框架自动生成,使用时无需显式地创建 如果调用修改了参数的默认初始化方式,框架会自动的将相关的修改加入default_startup_program - 2. fluid.default_main_program :定义了神经网络模型,前向反向计算,以及优化算法对网络中可学习参数的更新 - - 使用Fluid的核心就是构建起 default_main_program + 2. fluid.default_main_program :定义了神经网络模型,前向反向计算,以及模型参数更新、优化器参数更新等各种操作。 + 使用Paddle的核心就是构建起 default_main_program + ### Programs and Blocks -Fluid 的 Program 的基本结构是一些嵌套 blocks,形式上类似一段 C++ 或 Java 程序。 +Paddle 的 Program 的基本结构是一些嵌套 blocks,形式上类似一段 C++ 或 Java 程序。 blocks中包含: @@ -68,7 +66,7 @@ int main(){ //block 0 } ``` -类似的,在下列 Fluid 的 Program 包含3段block: +类似的,在下列 Paddle 的 Program 包含3段block: ```python import paddle.fluid as fluid # block 0 @@ -95,7 +93,7 @@ prob = ie() ``` ### BlockDesc and ProgramDesc -用户描述的block与program信息在Fluid中以[protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) 格式保存,所有的`protobuf`信息被定义在`framework.proto`中,在Fluid中被称为BlockDesc和ProgramDesc。ProgramDesc和BlockDesc的概念类似于一个[抽象语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree)。 +用户描述的block与program信息在Paddle中以[protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) 格式保存,所有的`protobuf`信息被定义在`framework.proto`中,在Paddle中被称为BlockDesc和ProgramDesc。ProgramDesc和BlockDesc的概念类似于一个[抽象语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree)。 `BlockDesc`中包含本地变量的定义 [vars](../../api_guides/low_level/program.html#variable),和一系列的operator`ops`: @@ -108,7 +106,7 @@ message BlockDesc { } ``` -parent ID表示父块,因此block中的操作符可以引用本地定义的变量,也可以引用祖先块中定义的变量。 +parent_idx表示父块,因此block中的操作符可以引用本地定义的变量,也可以引用祖先块中定义的变量。 Program 中的每层 block 都被压平并存储在数组中。blocks ID是这个数组中块的索引。 @@ -120,7 +118,7 @@ message ProgramDesc { ### 使用Blocks的Operator -[Programs and Blocks](#Programs and Blocks)的例子中,IfElseOp这个Operator包含了两个block——true分支和false分支。 +[Programs and Blocks](#ProgramsAndBlocks)的例子中,IfElseOp这个Operator包含了两个block——true分支和false分支。 下述OpDesc的定义过程描述了一个operator可以包含哪些属性: @@ -152,7 +150,7 @@ message AttrDesc { Executor 在运行时将接受一个`ProgramDesc`、一个`block_id`和一个`Scope`。`ProgramDesc`是`block`的列表,每一项包含`block`中所有参数和`operator`的`protobuf`定义;`block_id`指定入口块;`Scope`是所有变量实例的容器。 -其中 `Scope` 包含了 `name` 与 `Variable` 的映射,所有变量都被定义在 `Scope` 里。大部分API会默认使用 `global_scope` ,例如 :code:`Executor.run`,您也可以指定网络运行在某个特定的 `Scope` 中,一个网络可以在不同的 `Scope`内运行,并在该 `Scope` 内更新不同的 `Variable`。 +其中 `Scope` 包含了 `name` 与 `Variable` 的映射,所有变量都被定义在 `Scope` 里。大部分API会默认使用 `global_scope` ,例如 `Executor.run` ,您也可以指定网络运行在某个特定的 `Scope` 中,一个网络可以在不同的 `Scope`内运行,并在该 `Scope` 内更新不同的 `Variable`。 完成的编译执行的具体过程如下图所示: @@ -160,9 +158,9 @@ Executor 在运行时将接受一个`ProgramDesc`、一个`block_id`和一个`Sc -1. Executor 为每一个block创建一个Scope,Block是可嵌套的,因此Scope也是可嵌套的 -2. 创建所有Scope中的变量 -3. 按顺序创建并执行所有operator +1. Executor 为每一个block创建一个Scope,Block是可嵌套的,因此Scope也是可嵌套的。 +2. 创建所有Scope中的变量。 +3. 创建并执行所有operator。 @@ -182,7 +180,7 @@ class Executor{ scope->Var(Var->Name()); } - //创建OP并按顺序执行 + //创建OP并执行 for (auto& op_desc : block.AllOps()){ auto op = CreateOp(*op_desc); op->Run(*local_scope, place_); @@ -192,7 +190,7 @@ class Executor{ **创建Executor** -Fluid中使用fluid.Executor(place)创建Executor,place属性由用户定义,代表程序将在哪里执行。 +Paddle中使用fluid.Executor(place)创建Executor,place属性由用户定义,代表程序将在哪里执行。 下例代码表示创建一个Executor,其运行场所在CPU内: @@ -203,7 +201,7 @@ exe = fluid.Executor(cpu) **运行Executor** -Fluid使用Executor.run来运行程序。定义中通过Feed映射获取数据,通过fetch\_list获取结果: +Paddle使用Executor.run来运行程序。定义中通过Feed映射获取数据,通过fetch\_list获取结果: ```python ... @@ -215,11 +213,11 @@ outs = exe.run( ## 代码实例 -本节通过[Fluid编程指南](../../beginners_guide/programming_guide/programming_guide.html)中简单的线性回归例子,为您介绍上述内容如何在代码中实现。 +本节通过[编程指南](../../beginners_guide/programming_guide/programming_guide.html)中简单的线性回归例子,为您介绍上述内容如何在代码中实现。 **定义Program** -您可以随意定义自己的数据和网络结构,定义的结果都将作为一段 Program 被 Fluid 接收,Program 的基本结构是一些 blocks,本节的 Program 仅包含一个 block 0: +您可以随意定义自己的数据和网络结构,定义的结果都将作为一段 Program 被 Paddle 接收,Program 的基本结构是一些 blocks,本节的 Program 仅包含一个 block 0: ```python #加载函数库 @@ -230,8 +228,8 @@ import numpy train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32') y_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32') #定义网络 -x = fluid.layers.data(name="x",shape=[1],dtype='float32') -y = fluid.layers.data(name="y",shape=[1],dtype='float32') +x = fluid.data(name="x",shape=[None, 1],dtype='float32') +y = fluid.data(name="y",shape=[None, 1],dtype='float32') y_predict = fluid.layers.fc(input=x,size=1,act=None) #定义损失函数 cost = fluid.layers.square_error_cost(input=y_predict,label=y) @@ -298,9 +296,9 @@ blocks { ``` 从输出结果中可以看到,整个定义过程在框架内部转化为了一段ProgramDesc,以block idx为索引。本次线性回归模型中仅有1个block,ProgramDesc中也仅有block 0一段BlockDesc。 -BlockDesc中包含定义的 vars 和一系列的 ops,以输入x为例,python代码中定义 x 是一个数据类型为"float 32"的1维数据: +BlockDesc中包含定义的 vars 和一系列的 ops,以输入x为例,python代码中定义 x 是一个数据类型为"float32"的1维数据: ```python -x = fluid.layers.data(name="x",shape=[1],dtype='float32') +x = fluid.data(name="x",shape=[None, 1],dtype='float32') ``` 在BlockDesc中,变量x被描述为: ``` @@ -319,15 +317,15 @@ vars { } persistable: false ``` -在Fluid中所有的数据类型都为LoD-Tensor,对于不存在序列信息的数据(如此处的变量X),其lod_level=0。 +在Paddle中所有的数据类型都为LoD-Tensor,对于不存在序列信息的数据(如此处的变量X),其lod_level=0。 -dims表示数据的维度,这里表示 x 的维度为[-1,1],其中-1是batch的维度,无法确定具体数值时,Fluid 自动用 -1 占位。 +dims表示数据的维度,这里表示 x 的维度为[-1,1],其中-1是batch的维度,无法确定具体数值时,Paddle 自动用 -1 占位。 参数`persistable`表示该变量在整个训练过程中是否为持久化变量。 **创建Executor** -Fluid使用Executor来执行网络训练,Executor运行细节请参考[Executor设计思想](#Executor设计思想)的介绍。作为使用者,实际并不需要了解内部机制。 +Paddle使用Executor来执行网络训练,Executor运行细节请参考[Executor设计思想](#Executor设计思想)的介绍。作为使用者,实际并不需要了解内部机制。 创建Executor只需调用 fluid.Executor(place) 即可,在此之前请您依据训练场所定义place变量: ```python @@ -338,14 +336,14 @@ Fluid使用Executor来执行网络训练,Executor运行细节请参考[Executo ``` **运行Executor** -Fluid使用Executor.run来运行一段Program。 +Paddle使用Executor.run来运行一段Program。 -正式进行网络训练前,需先执行参数初始化。其中 defalut_startup_program 中定义了创建模型参数,输入输出,以及模型中可学习参数的初始化等各种操作。 +正式进行网络训练前,需先执行参数初始化。其中 defalut_startup_program 中定义了模型参数初始化、优化器参数初始化、reader初始化等各种操作。 ```python #参数初始化 exe.run(fluid.default_startup_program()) ``` -由于传入数据与传出数据存在多列,因此 fluid 通过 feed 映射定义数据的传输数据,通过 fetch_list 取出期望结果: +由于传入数据与传出数据存在多列,因此 Paddle 通过 feed 映射定义数据的传输数据,通过 fetch_list 取出期望结果: ```python #开始训练 outs = exe.run( @@ -362,5 +360,5 @@ Fluid使用Executor.run来运行一段Program。 [6.099215 ]], dtype=float32), array([1.6935859], dtype=float32)] ``` -至此您已经了解了Fluid 内部的执行流程的核心概念,更多框架使用细节请参考[使用指南](../../user_guides/index_cn.html)相关内容,[模型库](../../user_guides/models/index_cn.html +至此您已经了解了Paddle内部的执行流程的核心概念,更多框架使用细节请参考[使用指南](../../user_guides/index_cn.html)相关内容,[模型库](../../user_guides/models/index_cn.html )中也为您提供了丰富的模型示例以供参考。 diff --git a/doc/fluid/advanced_usage/design_idea/image/executor_design.png b/doc/fluid/advanced_usage/design_idea/image/executor_design.png index 0b3b7ad72fd487e4193beb41db7b7df748a2844c..ae0cf2f161da7d0700ecb4f63772d2bfc4c26de0 100644 Binary files a/doc/fluid/advanced_usage/design_idea/image/executor_design.png and b/doc/fluid/advanced_usage/design_idea/image/executor_design.png differ