Skip to content

Commit 515981d

Browse files
committed
Merge branch 'develop' into crf
2 parents d92c671 + b504a23 commit 515981d

File tree

192 files changed

+7903
-880
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+7903
-880
lines changed

CMakeLists.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ if(ANDROID OR IOS)
8686
"Disable MKLDNN when cross-compiling for Android and iOS" FORCE)
8787
set(WITH_MKLML OFF CACHE STRING
8888
"Disable MKLML package when cross-compiling for Android and iOS" FORCE)
89+
90+
# Compile PaddlePaddle mobile inference library
91+
if (NOT WITH_C_API)
92+
set(WITH_C_API ON CACHE STRING
93+
"Always compile the C_API when cross-compiling for Android and iOS" FORCE)
94+
endif()
95+
set(MOBILE_INFERENCE ON)
96+
add_definitions(-DPADDLE_MOBILE_INFERENCE)
8997
endif()
9098

9199
set(THIRD_PARTY_PATH "${CMAKE_BINARY_DIR}/third_party" CACHE STRING
@@ -160,9 +168,11 @@ endif(USE_NNPACK)
160168

161169
add_subdirectory(proto)
162170

163-
# "add_subdirectory(go)" should be placed after the following loine,
164-
# because it depends on paddle/optimizer.
165-
add_subdirectory(paddle/optimizer)
171+
if(NOT MOBILE_INFERENCE)
172+
# "add_subdirectory(go)" should be placed after the following loine,
173+
# because it depends on paddle/optimizer.
174+
add_subdirectory(paddle/optimizer)
175+
endif()
166176

167177
# "add_subdirectory(paddle)" and "add_subdirectory(python)" should be
168178
# placed after this block, because they depends on it.

cmake/configure.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ if(WITH_DOUBLE)
2424
add_definitions(-DPADDLE_TYPE_DOUBLE)
2525
endif(WITH_DOUBLE)
2626

27+
if(WITH_TESTING)
28+
add_definitions(-DPADDLE_WITH_TESTING)
29+
endif(WITH_TESTING)
30+
2731
if(NOT WITH_TIMER)
2832
add_definitions(-DPADDLE_DISABLE_TIMER)
2933
endif(NOT WITH_TIMER)

cmake/generic.cmake

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,60 @@ function(go_test TARGET_NAME)
389389
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
390390
endfunction(go_test)
391391

392+
# Modification of standard 'protobuf_generate_cpp()' with protobuf-lite support
393+
# Usage:
394+
# paddle_protobuf_generate_cpp(<proto_srcs> <proto_hdrs> <proto_files>)
395+
396+
function(paddle_protobuf_generate_cpp SRCS HDRS)
397+
if(NOT ARGN)
398+
message(SEND_ERROR "Error: paddle_protobuf_generate_cpp() called without any proto files")
399+
return()
400+
endif()
401+
402+
set(${SRCS})
403+
set(${HDRS})
404+
405+
if (MOBILE_INFERENCE)
406+
set(EXTRA_FLAG "lite:")
407+
else()
408+
set(EXTRA_FLAG "")
409+
endif()
410+
411+
foreach(FIL ${ARGN})
412+
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
413+
get_filename_component(FIL_WE ${FIL} NAME_WE)
414+
415+
set(_protobuf_protoc_src "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
416+
set(_protobuf_protoc_hdr "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
417+
list(APPEND ${SRCS} "${_protobuf_protoc_src}")
418+
list(APPEND ${HDRS} "${_protobuf_protoc_hdr}")
419+
420+
add_custom_command(
421+
OUTPUT "${_protobuf_protoc_src}"
422+
"${_protobuf_protoc_hdr}"
423+
424+
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}"
425+
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
426+
-I${CMAKE_CURRENT_SOURCE_DIR}
427+
--cpp_out "${EXTRA_FLAG}${CMAKE_CURRENT_BINARY_DIR}" ${ABS_FIL}
428+
DEPENDS ${ABS_FIL} protoc
429+
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
430+
VERBATIM )
431+
endforeach()
432+
433+
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
434+
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
435+
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
436+
endfunction()
437+
438+
392439
function(proto_library TARGET_NAME)
393440
set(oneValueArgs "")
394441
set(multiValueArgs SRCS DEPS)
395442
cmake_parse_arguments(proto_library "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
396443
set(proto_srcs)
397444
set(proto_hdrs)
398-
protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
445+
paddle_protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
399446
cc_library(${TARGET_NAME} SRCS ${proto_srcs} DEPS ${proto_library_DEPS} protobuf)
400447
endfunction()
401448

cmake/util.cmake

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,25 +73,43 @@ function(link_paddle_exe TARGET_NAME)
7373
generate_rdma_links()
7474
endif()
7575

76-
target_circle_link_libraries(${TARGET_NAME}
77-
ARCHIVE_START
78-
paddle_gserver
79-
paddle_function
80-
ARCHIVE_END
81-
paddle_pserver
82-
paddle_trainer_lib
83-
paddle_network
84-
paddle_math
85-
paddle_utils
86-
paddle_parameter
87-
paddle_proto
88-
paddle_cuda
89-
paddle_optimizer
90-
${EXTERNAL_LIBS}
91-
${CMAKE_THREAD_LIBS_INIT}
92-
${CMAKE_DL_LIBS}
93-
${RDMA_LD_FLAGS}
94-
${RDMA_LIBS})
76+
if(MOBILE_INFERENCE)
77+
target_circle_link_libraries(${TARGET_NAME}
78+
ARCHIVE_START
79+
paddle_gserver
80+
paddle_function
81+
ARCHIVE_END
82+
paddle_math
83+
paddle_utils
84+
paddle_parameter
85+
paddle_proto
86+
paddle_cuda
87+
${EXTERNAL_LIBS}
88+
${CMAKE_THREAD_LIBS_INIT}
89+
${CMAKE_DL_LIBS}
90+
${RDMA_LD_FLAGS}
91+
${RDMA_LIBS})
92+
else()
93+
target_circle_link_libraries(${TARGET_NAME}
94+
ARCHIVE_START
95+
paddle_gserver
96+
paddle_function
97+
ARCHIVE_END
98+
paddle_pserver
99+
paddle_trainer_lib
100+
paddle_network
101+
paddle_math
102+
paddle_utils
103+
paddle_parameter
104+
paddle_proto
105+
paddle_cuda
106+
paddle_optimizer
107+
${EXTERNAL_LIBS}
108+
${CMAKE_THREAD_LIBS_INIT}
109+
${CMAKE_DL_LIBS}
110+
${RDMA_LD_FLAGS}
111+
${RDMA_LIBS})
112+
endif()
95113

96114
if(ANDROID)
97115
target_link_libraries(${TARGET_NAME} log)

doc/design/block.md

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
Both deep learning systems and programming languages help users describe computation procedures. These systems use various representations of computation:
66

77
- Caffe, Torch, and Paddle: sequences of layers.
8-
- TensorFlow, Caffe2, Mxnet: graphs of operators.
8+
- TensorFlow, Caffe2, Mxnet: graph of operators.
99
- PaddlePaddle: nested blocks, like C++ and Java programs.
1010

1111
## Block in Programming Languages and Deep Learning
1212

13-
In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions, or operators.
13+
In programming languages, a block is a pair of curly braces that includes local variables definitions and a sequence of instructions or operators.
1414

1515
Blocks work with control flow structures like `if`, `else`, and `for`, which have equivalents in deep learning:
1616

@@ -24,14 +24,14 @@ A key difference is that a C++ program describes a one pass computation, whereas
2424

2525
## Stack Frames and the Scope Hierarchy
2626

27-
The existence of the backward makes the execution of a block of traditional programs and PaddlePaddle different to each other:
27+
The existence of the backward pass makes the execution of a block of PaddlePaddle different from traditional programs:
2828

29-
| programming languages | PaddlePaddle |
30-
|-----------------------|-------------------------------|
31-
| stack | scope hierarchy |
32-
| stack frame | scope |
33-
| push at entering block| push at entering block |
34-
| pop at leaving block | destroy at minibatch completes|
29+
| programming languages | PaddlePaddle |
30+
|-----------------------|---------------------------------|
31+
| stack | scope hierarchy |
32+
| stack frame | scope |
33+
| push at entering block| push at entering block |
34+
| pop at leaving block | destroy when minibatch completes|
3535

3636
1. In traditional programs:
3737

@@ -42,9 +42,9 @@ The existence of the backward makes the execution of a block of traditional prog
4242
1. In PaddlePaddle
4343

4444
- When the execution enters a block, PaddlePaddle adds a new scope, where it realizes variables.
45-
- PaddlePaddle doesn't pop a scope after the execution of the block because variables therein are to be used by the backward pass. So it has a stack forest known as a *scope hierarchy*.
45+
- PaddlePaddle doesn't pop a scope after the execution of the block because variables therein are used by the backward pass. So it has a stack forest known as a *scope hierarchy*.
4646
- The height of the highest tree is the maximum depth of nested blocks.
47-
- After the process of a minibatch, PaddlePaddle destroys the scope hierarchy.
47+
- After the processing of a minibatch, PaddlePaddle destroys the scope hierarchy.
4848

4949
## Use Blocks in C++ and PaddlePaddle Programs
5050

@@ -94,14 +94,14 @@ with ie.false_block():
9494
o1, o2 = ie(cond)
9595
```
9696

97-
In both examples, the left branch computes `x+y` and `softmax(x+y)`, the right branch computes `x+1` and `fc(x)`.
97+
In both examples, the left branch computes `x+y` and `softmax(x+y)`, the right branch computes `fc(x)` and `x+1` .
9898

99-
A difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances. The `ie.input(true, 0)` invocation returns instances in the 0-th input, `x`, that corresponds to true values in `cond` as the local variable `x`, where `ie.input(false, 0)` returns instances corresponding to false values.
99+
The difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances.
100100

101101

102102
### Blocks with `for` and `RNNOp`
103103

104-
The following RNN model from the [RNN design doc](./rnn.md)
104+
The following RNN model in PaddlePaddle from the [RNN design doc](./rnn.md) :
105105

106106
```python
107107
x = sequence([10, 20, 30]) # shape=[None, 1]
@@ -112,9 +112,9 @@ U = var(0.375, param=true) # shape=[1]
112112
rnn = pd.rnn()
113113
with rnn.step():
114114
h = rnn.memory(init = m)
115-
hh = rnn.previous_memory(h)
115+
h_prev = rnn.previous_memory(h)
116116
a = layer.fc(W, x)
117-
b = layer.fc(U, hh)
117+
b = layer.fc(U, h_prev)
118118
s = pd.add(a, b)
119119
act = pd.sigmoid(s)
120120
rnn.update_memory(h, act)
@@ -147,9 +147,9 @@ for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) {
147147

148148
## Compilation and Execution
149149

150-
Like TensorFlow programs, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest part executes the message for training or inference.
150+
Like TensorFlow, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest executes the message for training or inference.
151151

152-
The generation of this protobuf message is like what a compiler generates a binary executable file. The execution of the message that the OS executes the binary file.
152+
The generation of this protobuf message is similar to how a compiler generates a binary executable file. The execution of the message is similar to how the OS executes the binary file.
153153

154154
## The "Binary Executable File Format"
155155

@@ -186,8 +186,8 @@ Also, the RNN operator in above example is serialized into a protobuf message of
186186

187187
```
188188
OpDesc {
189-
inputs = {0} // the index of x
190-
outputs = {5, 3} // indices of act and hidden_out
189+
inputs = {0} // the index of x in vars of BlockDesc above
190+
outputs = {5, 3} // indices of act and hidden_out in vars of BlockDesc above
191191
attrs {
192192
"memories" : {1} // the index of h
193193
"step_net" : <above step net>
@@ -203,32 +203,32 @@ This `OpDesc` value is in the `ops` field of the `BlockDesc` value representing
203203
During the generation of the Protobuf message, the Block should store VarDesc (the Protobuf message which describes Variable) and OpDesc (the Protobuf message which describes Operator).
204204

205205
VarDesc in a block should have its name scope to avoid local variables affect parent block's name scope.
206-
Child block's name scopes should inherit the parent's so that OpDesc in child block can reference a VarDesc that stored in parent block. For example
206+
Child block's name scopes should inherit the parent's so that OpDesc in child block can reference a VarDesc that stored in parent block. For example:
207207

208208
```python
209-
a = pd.Varaible(shape=[20, 20])
209+
a = pd.Variable(shape=[20, 20])
210210
b = pd.fc(a, params=["fc.w", "fc.b"])
211211

212212
rnn = pd.create_rnn()
213-
with rnn.stepnet()
213+
with rnn.stepnet():
214214
x = a.as_step_input()
215215
# reuse fc's parameter
216216
fc_without_b = pd.get_variable("fc.w")
217217
rnn.output(fc_without_b)
218218

219219
out = rnn()
220220
```
221-
the method `pd.get_variable` can help retrieve a Variable by a name, a Variable may store in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance.
221+
The method `pd.get_variable` can help retrieve a Variable by the name. The Variable may be stored in a parent block, but might be retrieved in a child block, so block should have a variable scope that supports inheritance.
222222

223223
In compiler design, the symbol table is a data structure created and maintained by compilers to store information about the occurrence of various entities such as variable names, function names, classes, etc.
224224

225225
To store the definition of variables and operators, we define a C++ class `SymbolTable`, like the one used in compilers.
226226

227-
`SymbolTable` can do the following stuff:
227+
`SymbolTable` can do the following:
228228

229229
- store the definitions (some names and attributes) of variables and operators,
230-
- to verify if a variable was declared,
231-
- to make it possible to implement type checking (offer Protobuf message pointers to `InferShape` handlers).
230+
- verify if a variable was declared,
231+
- make it possible to implement type checking (offer Protobuf message pointers to `InferShape` handlers).
232232

233233

234234
```c++
@@ -240,19 +240,18 @@ class SymbolTable {
240240

241241
OpDesc* NewOp(const string& name="");
242242

243-
// TODO determine whether name is generated by python or C++
244-
// currently assume that a unique name will be generated by C++ if the
245-
// argument name left default.
243+
// TODO determine whether name is generated by python or C++.
244+
// Currently assume that a unique name will be generated by C++ if the
245+
// argument name is left default.
246246
VarDesc* NewVar(const string& name="");
247247

248-
// find a VarDesc by name, if recursive true, find parent's SymbolTable
248+
// find a VarDesc by name, if recursive is true, find parent's SymbolTable
249249
// recursively.
250250
// this interface is introduced to support InferShape, find protobuf messages
251251
// of variables and operators, pass pointers into InferShape.
252-
// operator
253252
//
254253
// NOTE maybe some C++ classes such as VarDescBuilder and OpDescBuilder should
255-
// be proposed and embedded into pybind to enable python operate on C++ pointers.
254+
// be proposed and embedded into pybind to enable python operation on C++ pointers.
256255
VarDesc* FindVar(const string& name, bool recursive=true);
257256

258257
OpDesc* FindOp(const string& name);
@@ -270,7 +269,7 @@ class SymbolTable {
270269
After all the description of variables and operators is added into SymbolTable,
271270
the block has enough information to run.
272271
273-
The `Block` class takes a `BlockDesc` as input, and provide `Run` and `InferShape` functions.
272+
The `Block` class takes a `BlockDesc` as input, and provides `Run` and `InferShape` functions.
274273
275274
276275
```c++
@@ -302,7 +301,7 @@ public:
302301
void CreateVariables(const framework::Scope& scope);
303302
void CreateOperators();
304303
305-
// some other necessary interfaces of NetOp are list below
304+
// some other necessary interfaces of NetOp are listed below
306305
// ...
307306
308307
private:
@@ -316,15 +315,14 @@ private:
316315
Block inherits from OperatorBase, which has a Run method.
317316
Block's Run method will run its operators sequentially.
318317

319-
There is another important interface called `Eval`, which take some arguments called targets, and generate a minimal graph which takes targets as the end points and creates a new Block,
320-
after `Run`, `Eval` will get the latest value and return the targets.
318+
There is another important interface called `Eval`, which takes some arguments called targets and generates a minimal graph which treats targets as the end points and creates a new Block. After `Run`, `Eval` will get the latest value and return the targets.
321319

322320
The definition of Eval is as follows:
323321

324322
```c++
325323
// clean a block description by targets using the corresponding dependency graph.
326324
// return a new BlockDesc with minimal number of operators.
327-
// NOTE not return a Block but the block's description so that this can be distributed
325+
// NOTE: The return type is not a Block but the block's description so that this can be distributed
328326
// to a cluster.
329327
BlockDesc Prune(const BlockDesc& desc, vector<string> targets);
330328

doc/design/dcgan.png

56.6 KB
Loading

0 commit comments

Comments
 (0)