Skip to content

Commit cb1baa3

Browse files
wangkuiyiabhinavarora
authored andcommitted
Update program.md (#4618)
* Update program.md * Update * Update
1 parent bfe6dcb commit cb1baa3

File tree

2 files changed

+94
-13
lines changed

2 files changed

+94
-13
lines changed

doc/design/program.md

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
# Design Doc: ProgramDesc
1+
# Design Doc: PaddlePaddle Programs
22

3-
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
3+
## Compile and Execution
4+
5+
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`.
46

5-
As described in [graph.md](./graph.md), the first five lines of the following PaddlePaddle program
7+
A simple example PaddlePaddle program can be found in [graph.md](./graph.md):
68

79
```python
810
x = layer.data("images")
@@ -13,36 +15,112 @@ optimize(cost)
1315
train(cost, reader=mnist.train())
1416
```
1517

16-
generates, or compiles, a PaddelPaddle program, which is represented by the following protobuf message:
18+
The first five lines of the following PaddlePaddle program generates, or, compiles, the `ProgramDesc` message. The last line runs it.
1719

18-
```protobuf
19-
message ProgramDesc {
20-
repeated BlockDesc blocks = 1;
20+
## Programs and Blocks
21+
22+
The basic structure of a PaddlePaddle program is some nested blocks, as a C++ or Java program.
23+
24+
- program: some nested blocks
25+
- [block](./block.md):
26+
- some local variable definitions, and
27+
- a sequence of operators
28+
29+
The concept of block comes from usual programs. For example, the following C++ program has three blocks:
30+
31+
```c++
32+
int main() { // block 0
33+
int i = 0;
34+
if (i < 10) { // block 1
35+
for (int j = 0; j < 10; j++) { // block 2
36+
}
37+
}
38+
return 0;
2139
}
40+
```
41+
42+
The following PaddlePaddle program has three blocks:
43+
44+
```python
45+
import paddle as pd // block 0
46+
47+
x = minibatch([10, 20, 30]) # shape=[None, 1]
48+
y = var(1) # shape=[1], value=1
49+
z = minibatch([10, 20, 30]) # shape=[None, 1]
50+
cond = larger_than(x, 15) # [false, true, true]
2251

52+
ie = pd.ifelse()
53+
with ie.true_block(): // block 1
54+
d = pd.layer.add_scalar(x, y)
55+
ie.output(d, pd.layer.softmax(d))
56+
with ie.false_block(): // block 2
57+
d = pd.layer.fc(z)
58+
ie.output(d, d+1)
59+
o1, o2 = ie(cond)
60+
```
61+
62+
## `BlockDesc` and `ProgramDesc`
63+
64+
All protobuf messages are defined in `framework.proto`.
65+
66+
`BlockDesc` is straight-forward -- it includes local variable definitions, `vars`, and a sequence of operators, `ops`.
67+
68+
```protobuf
2369
message BlockDesc {
2470
required int32 parent = 1;
2571
repeated VarDesc vars = 2;
2672
repeated OpDesc ops = 3;
2773
}
74+
```
75+
76+
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.
77+
78+
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.
79+
80+
```protobuf
81+
message ProgramDesc {
82+
repeated BlockDesc blocks = 1;
83+
}
84+
```
85+
86+
87+
### Global Block
2888

89+
The global block is the first one in the above array.
90+
91+
## Operators that Use Blocks
92+
93+
In the above example, the operator `IfElseOp` has two blocks -- the true branch and the false branch.
94+
95+
The definition of `OpDesc` shows that an operator could have some attributes:
96+
97+
```protobuf
2998
message OpDesc {
3099
AttrDesc attrs = 1;
31100
...
32101
}
102+
```
103+
104+
and an attribute could be of type block, which is, in fact, a block ID as described above:
33105

106+
```
34107
message AttrDesc {
35-
required AttrType type = 1;
108+
required string name = 1;
36109
37-
// index into ProgramDesc::blocks when type==BLOCK
38-
optional int32 block = 2;
110+
enum AttrType {
111+
INT = 1,
112+
STRING = 2,
113+
...
114+
BLOCK = ...
115+
}
116+
required AttrType type = 2;
117+
118+
optional int32 block = 10; // when type == BLOCK
39119
...
40120
}
41121
```
42122

43-
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.
44-
45-
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.
123+
## InferShape
46124

47125
With this design, the InferShape function should take the following parameters:
48126

paddle/framework/framework.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,7 @@ message BlockDesc {
115115
repeated OpDesc ops = 4;
116116
}
117117

118+
// Please refer to
119+
// https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md
120+
// for more details.
118121
message ProgramDesc { repeated BlockDesc blocks = 1; }

0 commit comments

Comments
 (0)