提交 cd0aa31e 编写于 作者: T Travis CI

Deploy to GitHub Pages: cb1baa3b

上级 8cc9d887
# Design Doc: ProgramDesc
# Design Doc: PaddlePaddle Programs
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
## Compile and Execution
A PaddlePaddle program consists of two parts -- the first generates a `ProgramDesc` protobuf message that describes the program, and the second runs this message using a C++ class `Executor`.
As described in [graph.md](./graph.md), the first five lines of the following PaddlePaddle program
A simple example PaddlePaddle program can be found in [graph.md](./graph.md):
```python
x = layer.data("images")
......@@ -13,36 +15,112 @@ optimize(cost)
train(cost, reader=mnist.train())
```
generates, or compiles, a PaddelPaddle program, which is represented by the following protobuf message:
The first five lines of the following PaddlePaddle program generates, or, compiles, the `ProgramDesc` message. The last line runs it.
```protobuf
message ProgramDesc {
repeated BlockDesc blocks = 1;
## Programs and Blocks
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
- program: some nested blocks
- [block](./block.md):
- some local variable definitions, and
- a sequence of operators
The concept of block comes from usual programs. For example, the following C++ program has three blocks:
```c++
int main() { // block 0
int i = 0;
if (i < 10) { // block 1
for (int j = 0; j < 10; j++) { // block 2
}
}
return 0;
}
```
The following PaddlePaddle program has three blocks:
```python
import paddle as pd // block 0
x = minibatch([10, 20, 30]) # shape=[None, 1]
y = var(1) # shape=[1], value=1
z = minibatch([10, 20, 30]) # shape=[None, 1]
cond = larger_than(x, 15) # [false, true, true]
ie = pd.ifelse()
with ie.true_block(): // block 1
d = pd.layer.add_scalar(x, y)
ie.output(d, pd.layer.softmax(d))
with ie.false_block(): // block 2
d = pd.layer.fc(z)
ie.output(d, d+1)
o1, o2 = ie(cond)
```
## `BlockDesc` and `ProgramDesc`
All protobuf messages are defined in `framework.proto`.
`BlockDesc` is straight-forward -- it includes local variable definitions, `vars`, and a sequence of operators, `ops`.
```protobuf
message BlockDesc {
required int32 parent = 1;
repeated VarDesc vars = 2;
repeated OpDesc ops = 3;
}
```
The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.
All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.
```protobuf
message ProgramDesc {
repeated BlockDesc blocks = 1;
}
```
### Global Block
The global block is the first one in the above array.
## Operators that Use Blocks
In the above example, the operator `IfElseOp` has two blocks -- the true branch and the false branch.
The definition of `OpDesc` shows that an operator could have some attributes:
```protobuf
message OpDesc {
AttrDesc attrs = 1;
...
}
```
and an attribute could be of type block, which is, in fact, a block ID as described above:
```
message AttrDesc {
required AttrType type = 1;
required string name = 1;
// index into ProgramDesc::blocks when type==BLOCK
optional int32 block = 2;
enum AttrType {
INT = 1,
STRING = 2,
...
BLOCK = ...
}
required AttrType type = 2;
optional int32 block = 10; // when type == BLOCK
...
}
```
When each of the first five lines runs, related Python function, e.g., `layer.fc`, calls C++ InferShape functions. This InferShape function needs to access the properties of VarDesc's accessed by the current OpDesc. These VarDesc's might not be defined in the current block, but in some ancestor blocks. This requires that we can trace the parent of a block.
A nested block is often an attribute of an operator, most likely, an IfElseOp or a WhileOp. In above solution, all blocks are in `ProgramDesc::blocks`, this implicitly assigns a zero-based ID to each block -- the index of the block in `ProgramDesc::blocks`. So that `AttrDesc::block` could be an integer block ID.
## InferShape
With this design, the InferShape function should take the following parameters:
......
......@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Design Doc: ProgramDesc &mdash; PaddlePaddle documentation</title>
<title>Design Doc: PaddlePaddle Programs &mdash; PaddlePaddle documentation</title>
......@@ -168,7 +168,7 @@
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li>Design Doc: ProgramDesc</li>
<li>Design Doc: PaddlePaddle Programs</li>
</ul>
</div>
......@@ -177,10 +177,12 @@
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="design-doc-programdesc">
<span id="design-doc-programdesc"></span><h1>Design Doc: ProgramDesc<a class="headerlink" href="#design-doc-programdesc" title="Permalink to this headline"></a></h1>
<p>The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.</p>
<p>As described in <a class="reference internal" href="graph.html"><span class="doc">graph.md</span></a>, the first five lines of the following PaddlePaddle program</p>
<div class="section" id="design-doc-paddlepaddle-programs">
<span id="design-doc-paddlepaddle-programs"></span><h1>Design Doc: PaddlePaddle Programs<a class="headerlink" href="#design-doc-paddlepaddle-programs" title="Permalink to this headline"></a></h1>
<div class="section" id="compile-and-execution">
<span id="compile-and-execution"></span><h2>Compile and Execution<a class="headerlink" href="#compile-and-execution" title="Permalink to this headline"></a></h2>
<p>A PaddlePaddle program consists of two parts &#8211; the first generates a <code class="docutils literal"><span class="pre">ProgramDesc</span></code> protobuf message that describes the program, and the second runs this message using a C++ class <code class="docutils literal"><span class="pre">Executor</span></code>.</p>
<p>A simple example PaddlePaddle program can be found in <a class="reference internal" href="graph.html"><span class="doc">graph.md</span></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">data</span><span class="p">(</span><span class="s2">&quot;images&quot;</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">data</span><span class="p">(</span><span class="s2">&quot;label&quot;</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">fc</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
......@@ -189,33 +191,102 @@
<span class="n">train</span><span class="p">(</span><span class="n">cost</span><span class="p">,</span> <span class="n">reader</span><span class="o">=</span><span class="n">mnist</span><span class="o">.</span><span class="n">train</span><span class="p">())</span>
</pre></div>
</div>
<p>generates, or compiles, a PaddelPaddle program, which is represented by the following protobuf message:</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">ProgramDesc</span> <span class="p">{</span>
<span class="k">repeated</span> <span class="n">BlockDesc</span> <span class="na">blocks</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<p>The first five lines of the following PaddlePaddle program generates, or, compiles, the <code class="docutils literal"><span class="pre">ProgramDesc</span></code> message. The last line runs it.</p>
</div>
<div class="section" id="programs-and-blocks">
<span id="programs-and-blocks"></span><h2>Programs and Blocks<a class="headerlink" href="#programs-and-blocks" title="Permalink to this headline"></a></h2>
<p>The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.</p>
<ul class="simple">
<li>program: some nested blocks</li>
<li><a class="reference internal" href="block.html"><span class="doc">block</span></a>:<ul>
<li>some local variable definitions, and</li>
<li>a sequence of operators</li>
</ul>
</li>
</ul>
<p>The concept of block comes from usual programs. For example, the following C++ program has three blocks:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// block 0</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// block 1</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// block 2</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">BlockDesc</span> <span class="p">{</span>
</pre></div>
</div>
<p>The following PaddlePaddle program has three blocks:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">paddle</span> <span class="kn">as</span> <span class="nn">pd</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">0</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">minibatch</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">])</span> <span class="c1"># shape=[None, 1]</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">var</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># shape=[1], value=1</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">minibatch</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">])</span> <span class="c1"># shape=[None, 1]</span>
<span class="n">cond</span> <span class="o">=</span> <span class="n">larger_than</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span> <span class="c1"># [false, true, true]</span>
<span class="n">ie</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">ifelse</span><span class="p">()</span>
<span class="k">with</span> <span class="n">ie</span><span class="o">.</span><span class="n">true_block</span><span class="p">():</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">1</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">add_scalar</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="n">ie</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">softmax</span><span class="p">(</span><span class="n">d</span><span class="p">))</span>
<span class="k">with</span> <span class="n">ie</span><span class="o">.</span><span class="n">false_block</span><span class="p">():</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">2</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">fc</span><span class="p">(</span><span class="n">z</span><span class="p">)</span>
<span class="n">ie</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="n">o1</span><span class="p">,</span> <span class="n">o2</span> <span class="o">=</span> <span class="n">ie</span><span class="p">(</span><span class="n">cond</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="blockdesc-and-programdesc">
<span id="blockdesc-and-programdesc"></span><h2><code class="docutils literal"><span class="pre">BlockDesc</span></code> and <code class="docutils literal"><span class="pre">ProgramDesc</span></code><a class="headerlink" href="#blockdesc-and-programdesc" title="Permalink to this headline"></a></h2>
<p>All protobuf messages are defined in <code class="docutils literal"><span class="pre">framework.proto</span></code>.</p>
<p><code class="docutils literal"><span class="pre">BlockDesc</span></code> is straight-forward &#8211; it includes local variable definitions, <code class="docutils literal"><span class="pre">vars</span></code>, and a sequence of operators, <code class="docutils literal"><span class="pre">ops</span></code>.</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">BlockDesc</span> <span class="p">{</span>
<span class="k">required</span> <span class="kt">int32</span> <span class="na">parent</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">repeated</span> <span class="n">VarDesc</span> <span class="na">vars</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">repeated</span> <span class="n">OpDesc</span> <span class="na">ops</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">OpDesc</span> <span class="p">{</span>
</pre></div>
</div>
<p>The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.</p>
<p>All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">ProgramDesc</span> <span class="p">{</span>
<span class="k">repeated</span> <span class="n">BlockDesc</span> <span class="na">blocks</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="global-block">
<span id="global-block"></span><h3>Global Block<a class="headerlink" href="#global-block" title="Permalink to this headline"></a></h3>
<p>The global block is the first one in the above array.</p>
</div>
</div>
<div class="section" id="operators-that-use-blocks">
<span id="operators-that-use-blocks"></span><h2>Operators that Use Blocks<a class="headerlink" href="#operators-that-use-blocks" title="Permalink to this headline"></a></h2>
<p>In the above example, the operator <code class="docutils literal"><span class="pre">IfElseOp</span></code> has two blocks &#8211; the true branch and the false branch.</p>
<p>The definition of <code class="docutils literal"><span class="pre">OpDesc</span></code> shows that an operator could have some attributes:</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">OpDesc</span> <span class="p">{</span>
<span class="n">AttrDesc</span> <span class="na">attrs</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="o">...</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">AttrDesc</span> <span class="p">{</span>
<span class="k">required</span> <span class="n">AttrType</span> <span class="na">type</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">// index into ProgramDesc::blocks when type==BLOCK</span>
<span class="k">optional</span> <span class="kt">int32</span> <span class="na">block</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</pre></div>
</div>
<p>and an attribute could be of type block, which is, in fact, a block ID as described above:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">message</span> <span class="n">AttrDesc</span> <span class="p">{</span>
<span class="n">required</span> <span class="n">string</span> <span class="n">name</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">enum</span> <span class="n">AttrType</span> <span class="p">{</span>
<span class="n">INT</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
<span class="n">STRING</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
<span class="o">...</span>
<span class="n">BLOCK</span> <span class="o">=</span> <span class="o">...</span>
<span class="p">}</span>
<span class="n">required</span> <span class="n">AttrType</span> <span class="nb">type</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">optional</span> <span class="n">int32</span> <span class="n">block</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="o">//</span> <span class="n">when</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">BLOCK</span>
<span class="o">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>When each of the first five lines runs, related Python function, e.g., <code class="docutils literal"><span class="pre">layer.fc</span></code>, calls C++ InferShape functions. This InferShape function needs to access the properties of VarDesc&#8217;s accessed by the current OpDesc. These VarDesc&#8217;s might not be defined in the current block, but in some ancestor blocks. This requires that we can trace the parent of a block.</p>
<p>A nested block is often an attribute of an operator, most likely, an IfElseOp or a WhileOp. In above solution, all blocks are in <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>, this implicitly assigns a zero-based ID to each block &#8211; the index of the block in <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>. So that <code class="docutils literal"><span class="pre">AttrDesc::block</span></code> could be an integer block ID.</p>
</div>
<div class="section" id="infershape">
<span id="infershape"></span><h2>InferShape<a class="headerlink" href="#infershape" title="Permalink to this headline"></a></h2>
<p>With this design, the InferShape function should take the following parameters:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">InferShape</span><span class="p">(</span><span class="kt">int</span> <span class="n">current_block</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">current_operator</span><span class="p">,</span>
......@@ -230,6 +301,7 @@
<li><code class="docutils literal"><span class="pre">current_block</span></code> indices into <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>,</li>
<li><code class="docutils literal"><span class="pre">current_operator</span></code> indices into <code class="docutils literal"><span class="pre">BlockDesc::ops</span></code>.</li>
</ul>
</div>
</div>
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
# Design Doc: ProgramDesc
# Design Doc: PaddlePaddle Programs
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
## Compile and Execution
A PaddlePaddle program consists of two parts -- the first generates a `ProgramDesc` protobuf message that describes the program, and the second runs this message using a C++ class `Executor`.
As described in [graph.md](./graph.md), the first five lines of the following PaddlePaddle program
A simple example PaddlePaddle program can be found in [graph.md](./graph.md):
```python
x = layer.data("images")
......@@ -13,36 +15,112 @@ optimize(cost)
train(cost, reader=mnist.train())
```
generates, or compiles, a PaddelPaddle program, which is represented by the following protobuf message:
The first five lines of the following PaddlePaddle program generates, or, compiles, the `ProgramDesc` message. The last line runs it.
```protobuf
message ProgramDesc {
repeated BlockDesc blocks = 1;
## Programs and Blocks
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
- program: some nested blocks
- [block](./block.md):
- some local variable definitions, and
- a sequence of operators
The concept of block comes from usual programs. For example, the following C++ program has three blocks:
```c++
int main() { // block 0
int i = 0;
if (i < 10) { // block 1
for (int j = 0; j < 10; j++) { // block 2
}
}
return 0;
}
```
The following PaddlePaddle program has three blocks:
```python
import paddle as pd // block 0
x = minibatch([10, 20, 30]) # shape=[None, 1]
y = var(1) # shape=[1], value=1
z = minibatch([10, 20, 30]) # shape=[None, 1]
cond = larger_than(x, 15) # [false, true, true]
ie = pd.ifelse()
with ie.true_block(): // block 1
d = pd.layer.add_scalar(x, y)
ie.output(d, pd.layer.softmax(d))
with ie.false_block(): // block 2
d = pd.layer.fc(z)
ie.output(d, d+1)
o1, o2 = ie(cond)
```
## `BlockDesc` and `ProgramDesc`
All protobuf messages are defined in `framework.proto`.
`BlockDesc` is straight-forward -- it includes local variable definitions, `vars`, and a sequence of operators, `ops`.
```protobuf
message BlockDesc {
required int32 parent = 1;
repeated VarDesc vars = 2;
repeated OpDesc ops = 3;
}
```
The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.
All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.
```protobuf
message ProgramDesc {
repeated BlockDesc blocks = 1;
}
```
### Global Block
The global block is the first one in the above array.
## Operators that Use Blocks
In the above example, the operator `IfElseOp` has two blocks -- the true branch and the false branch.
The definition of `OpDesc` shows that an operator could have some attributes:
```protobuf
message OpDesc {
AttrDesc attrs = 1;
...
}
```
and an attribute could be of type block, which is, in fact, a block ID as described above:
```
message AttrDesc {
required AttrType type = 1;
required string name = 1;
// index into ProgramDesc::blocks when type==BLOCK
optional int32 block = 2;
enum AttrType {
INT = 1,
STRING = 2,
...
BLOCK = ...
}
required AttrType type = 2;
optional int32 block = 10; // when type == BLOCK
...
}
```
When each of the first five lines runs, related Python function, e.g., `layer.fc`, calls C++ InferShape functions. This InferShape function needs to access the properties of VarDesc's accessed by the current OpDesc. These VarDesc's might not be defined in the current block, but in some ancestor blocks. This requires that we can trace the parent of a block.
A nested block is often an attribute of an operator, most likely, an IfElseOp or a WhileOp. In above solution, all blocks are in `ProgramDesc::blocks`, this implicitly assigns a zero-based ID to each block -- the index of the block in `ProgramDesc::blocks`. So that `AttrDesc::block` could be an integer block ID.
## InferShape
With this design, the InferShape function should take the following parameters:
......
......@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Design Doc: ProgramDesc &mdash; PaddlePaddle 文档</title>
<title>Design Doc: PaddlePaddle Programs &mdash; PaddlePaddle 文档</title>
......@@ -182,7 +182,7 @@
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li>Design Doc: ProgramDesc</li>
<li>Design Doc: PaddlePaddle Programs</li>
</ul>
</div>
......@@ -191,10 +191,12 @@
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="design-doc-programdesc">
<span id="design-doc-programdesc"></span><h1>Design Doc: ProgramDesc<a class="headerlink" href="#design-doc-programdesc" title="永久链接至标题"></a></h1>
<p>The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.</p>
<p>As described in <a class="reference internal" href="graph.html"><span class="doc">graph.md</span></a>, the first five lines of the following PaddlePaddle program</p>
<div class="section" id="design-doc-paddlepaddle-programs">
<span id="design-doc-paddlepaddle-programs"></span><h1>Design Doc: PaddlePaddle Programs<a class="headerlink" href="#design-doc-paddlepaddle-programs" title="永久链接至标题"></a></h1>
<div class="section" id="compile-and-execution">
<span id="compile-and-execution"></span><h2>Compile and Execution<a class="headerlink" href="#compile-and-execution" title="永久链接至标题"></a></h2>
<p>A PaddlePaddle program consists of two parts &#8211; the first generates a <code class="docutils literal"><span class="pre">ProgramDesc</span></code> protobuf message that describes the program, and the second runs this message using a C++ class <code class="docutils literal"><span class="pre">Executor</span></code>.</p>
<p>A simple example PaddlePaddle program can be found in <a class="reference internal" href="graph.html"><span class="doc">graph.md</span></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">data</span><span class="p">(</span><span class="s2">&quot;images&quot;</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">data</span><span class="p">(</span><span class="s2">&quot;label&quot;</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">fc</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
......@@ -203,33 +205,102 @@
<span class="n">train</span><span class="p">(</span><span class="n">cost</span><span class="p">,</span> <span class="n">reader</span><span class="o">=</span><span class="n">mnist</span><span class="o">.</span><span class="n">train</span><span class="p">())</span>
</pre></div>
</div>
<p>generates, or compiles, a PaddelPaddle program, which is represented by the following protobuf message:</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">ProgramDesc</span> <span class="p">{</span>
<span class="k">repeated</span> <span class="n">BlockDesc</span> <span class="na">blocks</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<p>The first five lines of the following PaddlePaddle program generates, or, compiles, the <code class="docutils literal"><span class="pre">ProgramDesc</span></code> message. The last line runs it.</p>
</div>
<div class="section" id="programs-and-blocks">
<span id="programs-and-blocks"></span><h2>Programs and Blocks<a class="headerlink" href="#programs-and-blocks" title="永久链接至标题"></a></h2>
<p>The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.</p>
<ul class="simple">
<li>program: some nested blocks</li>
<li><a class="reference internal" href="block.html"><span class="doc">block</span></a>:<ul>
<li>some local variable definitions, and</li>
<li>a sequence of operators</li>
</ul>
</li>
</ul>
<p>The concept of block comes from usual programs. For example, the following C++ program has three blocks:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// block 0</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// block 1</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// block 2</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">BlockDesc</span> <span class="p">{</span>
</pre></div>
</div>
<p>The following PaddlePaddle program has three blocks:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">paddle</span> <span class="kn">as</span> <span class="nn">pd</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">0</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">minibatch</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">])</span> <span class="c1"># shape=[None, 1]</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">var</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># shape=[1], value=1</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">minibatch</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">])</span> <span class="c1"># shape=[None, 1]</span>
<span class="n">cond</span> <span class="o">=</span> <span class="n">larger_than</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span> <span class="c1"># [false, true, true]</span>
<span class="n">ie</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">ifelse</span><span class="p">()</span>
<span class="k">with</span> <span class="n">ie</span><span class="o">.</span><span class="n">true_block</span><span class="p">():</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">1</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">add_scalar</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="n">ie</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">softmax</span><span class="p">(</span><span class="n">d</span><span class="p">))</span>
<span class="k">with</span> <span class="n">ie</span><span class="o">.</span><span class="n">false_block</span><span class="p">():</span> <span class="o">//</span> <span class="n">block</span> <span class="mi">2</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">layer</span><span class="o">.</span><span class="n">fc</span><span class="p">(</span><span class="n">z</span><span class="p">)</span>
<span class="n">ie</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">d</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="n">o1</span><span class="p">,</span> <span class="n">o2</span> <span class="o">=</span> <span class="n">ie</span><span class="p">(</span><span class="n">cond</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="blockdesc-and-programdesc">
<span id="blockdesc-and-programdesc"></span><h2><code class="docutils literal"><span class="pre">BlockDesc</span></code> and <code class="docutils literal"><span class="pre">ProgramDesc</span></code><a class="headerlink" href="#blockdesc-and-programdesc" title="永久链接至标题"></a></h2>
<p>All protobuf messages are defined in <code class="docutils literal"><span class="pre">framework.proto</span></code>.</p>
<p><code class="docutils literal"><span class="pre">BlockDesc</span></code> is straight-forward &#8211; it includes local variable definitions, <code class="docutils literal"><span class="pre">vars</span></code>, and a sequence of operators, <code class="docutils literal"><span class="pre">ops</span></code>.</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">BlockDesc</span> <span class="p">{</span>
<span class="k">required</span> <span class="kt">int32</span> <span class="na">parent</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">repeated</span> <span class="n">VarDesc</span> <span class="na">vars</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">repeated</span> <span class="n">OpDesc</span> <span class="na">ops</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">OpDesc</span> <span class="p">{</span>
</pre></div>
</div>
<p>The parent ID indicates the parent block so that operators in a block can refer to variables defined locally and also those defined in their ancestor blocks.</p>
<p>All hierarchical blocks in a program are flattened and stored in an array. The block ID is the index of the block in this array.</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">ProgramDesc</span> <span class="p">{</span>
<span class="k">repeated</span> <span class="n">BlockDesc</span> <span class="na">blocks</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="global-block">
<span id="global-block"></span><h3>Global Block<a class="headerlink" href="#global-block" title="永久链接至标题"></a></h3>
<p>The global block is the first one in the above array.</p>
</div>
</div>
<div class="section" id="operators-that-use-blocks">
<span id="operators-that-use-blocks"></span><h2>Operators that Use Blocks<a class="headerlink" href="#operators-that-use-blocks" title="永久链接至标题"></a></h2>
<p>In the above example, the operator <code class="docutils literal"><span class="pre">IfElseOp</span></code> has two blocks &#8211; the true branch and the false branch.</p>
<p>The definition of <code class="docutils literal"><span class="pre">OpDesc</span></code> shows that an operator could have some attributes:</p>
<div class="highlight-protobuf"><div class="highlight"><pre><span></span><span class="kd">message</span> <span class="nc">OpDesc</span> <span class="p">{</span>
<span class="n">AttrDesc</span> <span class="na">attrs</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="o">...</span>
<span class="p">}</span>
<span class="kd">message</span> <span class="nc">AttrDesc</span> <span class="p">{</span>
<span class="k">required</span> <span class="n">AttrType</span> <span class="na">type</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">// index into ProgramDesc::blocks when type==BLOCK</span>
<span class="k">optional</span> <span class="kt">int32</span> <span class="na">block</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</pre></div>
</div>
<p>and an attribute could be of type block, which is, in fact, a block ID as described above:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">message</span> <span class="n">AttrDesc</span> <span class="p">{</span>
<span class="n">required</span> <span class="n">string</span> <span class="n">name</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">enum</span> <span class="n">AttrType</span> <span class="p">{</span>
<span class="n">INT</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
<span class="n">STRING</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
<span class="o">...</span>
<span class="n">BLOCK</span> <span class="o">=</span> <span class="o">...</span>
<span class="p">}</span>
<span class="n">required</span> <span class="n">AttrType</span> <span class="nb">type</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">optional</span> <span class="n">int32</span> <span class="n">block</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="o">//</span> <span class="n">when</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">BLOCK</span>
<span class="o">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>When each of the first five lines runs, related Python function, e.g., <code class="docutils literal"><span class="pre">layer.fc</span></code>, calls C++ InferShape functions. This InferShape function needs to access the properties of VarDesc&#8217;s accessed by the current OpDesc. These VarDesc&#8217;s might not be defined in the current block, but in some ancestor blocks. This requires that we can trace the parent of a block.</p>
<p>A nested block is often an attribute of an operator, most likely, an IfElseOp or a WhileOp. In above solution, all blocks are in <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>, this implicitly assigns a zero-based ID to each block &#8211; the index of the block in <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>. So that <code class="docutils literal"><span class="pre">AttrDesc::block</span></code> could be an integer block ID.</p>
</div>
<div class="section" id="infershape">
<span id="infershape"></span><h2>InferShape<a class="headerlink" href="#infershape" title="永久链接至标题"></a></h2>
<p>With this design, the InferShape function should take the following parameters:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">InferShape</span><span class="p">(</span><span class="kt">int</span> <span class="n">current_block</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">current_operator</span><span class="p">,</span>
......@@ -244,6 +315,7 @@
<li><code class="docutils literal"><span class="pre">current_block</span></code> indices into <code class="docutils literal"><span class="pre">ProgramDesc::blocks</span></code>,</li>
<li><code class="docutils literal"><span class="pre">current_operator</span></code> indices into <code class="docutils literal"><span class="pre">BlockDesc::ops</span></code>.</li>
</ul>
</div>
</div>
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册