Skip to content

Commit c6d500a

Browse files
committed
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into develop
2 parents 44da4e4 + 2f3097b commit c6d500a

File tree

21 files changed

+373
-38
lines changed

21 files changed

+373
-38
lines changed

.gitmodules

Lines changed: 0 additions & 4 deletions
This file was deleted.

book

Lines changed: 0 additions & 1 deletion
This file was deleted.

demo/introduction/api_train_v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def main():
1414
act=paddle.activation.Linear(),
1515
bias_attr=paddle.attr.Param(name='b'))
1616
y = paddle.layer.data(name='y', type=paddle.data_type.dense_vector(1))
17-
cost = paddle.layer.regression_cost(input=y_predict, label=y)
17+
cost = paddle.layer.mse_cost(input=y_predict, label=y)
1818

1919
# create parameters
2020
parameters = paddle.parameters.create(cost)

demo/introduction/trainer_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@
3434
size=1,
3535
act=LinearActivation(),
3636
bias_attr=ParamAttr(name='b'))
37-
cost = regression_cost(input=y_predict, label=y)
37+
cost = mse_cost(input=y_predict, label=y)
3838
outputs(cost)

demo/recommendation/api_train_v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def main():
6161

6262
inference = paddle.layer.cos_sim(
6363
a=usr_combined_features, b=mov_combined_features, size=1, scale=5)
64-
cost = paddle.layer.regression_cost(
64+
cost = paddle.layer.mse_cost(
6565
input=inference,
6666
label=paddle.layer.data(
6767
name='score', type=paddle.data_type.dense_vector(1)))

demo/recommendation/trainer_config.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ def construct_feature(name):
8686
user_feature = construct_feature("user")
8787
similarity = cos_sim(a=movie_feature, b=user_feature)
8888
if not is_predict:
89-
outputs(
90-
regression_cost(
91-
input=similarity, label=data_layer(
92-
'rating', size=1)))
89+
outputs(mse_cost(input=similarity, label=data_layer('rating', size=1)))
9390

9491
define_py_data_sources2(
9592
'data/train.list',

doc/api/v1/trainer_config_helpers/layers.rst

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ multi_binary_label_cross_entropy
432432
:members: multi_binary_label_cross_entropy
433433
:noindex:
434434

435+
mse_cost
436+
---------
437+
.. automodule:: paddle.trainer_config_helpers.layers
438+
:members: mse_cost
439+
:noindex:
440+
435441
huber_cost
436442
----------
437443
.. automodule:: paddle.trainer_config_helpers.layers
@@ -450,6 +456,12 @@ rank_cost
450456
:members: rank_cost
451457
:noindex:
452458

459+
sum_cost
460+
---------
461+
.. automodule:: paddle.trainer_config_helpers.layers
462+
:members: sum_cost
463+
:noindex:
464+
453465
crf_layer
454466
-----------------
455467
.. automodule:: paddle.trainer_config_helpers.layers
@@ -486,12 +498,6 @@ hsigmoid
486498
:members: hsigmoid
487499
:noindex:
488500

489-
sum_cost
490-
---------
491-
.. automodule:: paddle.trainer_config_helpers.layers
492-
:members: sum_cost
493-
:noindex:
494-
495501
Check Layer
496502
============
497503

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Paddle多语言接口实现
2+
## 背景
3+
4+
Paddle需要一个多语言接口,这个接口需要做到:
5+
6+
* 有标准的,良好的文档
7+
* 例如Python可以使用[Sphinx](http://www.sphinx-doc.org/en/stable/)生成API文档,golang可以使用[GoDoc](https://godoc.org/golang.org/x/tools/cmd/godoc)生成文档。这都需要这个接口按照约定俗成的规则来注释完备。
8+
* 不同语言的接口适应不同语言的特性
9+
* 例如Java与Python的错误处理是直接扔出来Exception,而对于golang错误处理应该使用返回值。
10+
11+
## 基本要求
12+
13+
Paddle的多语言接口实现包括一下几个方面:
14+
15+
* 我们使用动态库来分发Paddle。在这个动态库中不嵌入任何其他语言的解释器,也不使用其他动态库。
16+
* 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号。
17+
* 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler)。
18+
* 不使用SWIG这种代码生成器,而是手写多语言绑定。
19+
20+
21+
## 原因
22+
23+
### 使用动态库来分发Paddle
24+
25+
* Paddle的链接方式比较复杂
26+
* 如果用户要把Paddle的静态库(libpaddle.a)链接到自己的程序里,得使用 `--whole-archive` (for GCC) 或者 `--force_load` (for Clang) 参数,来确保把 libpaddle.a 里所有的符号都写入自己的程序的二进制文件里。这是因为 Paddle 的源码里使用了[object factory design pattern](http://stackoverflow.com/a/1310326/724872)
27+
* 编译型语言,例如C/C++使用静态库和动态库难度差不多。但是解释性语言,例如[Python](http://stackoverflow.com/questions/19560594/how-to-import-static-library-in-python)或者[Java](http://stackoverflow.com/questions/24493337/linking-static-library-with-jni),只能调用Paddle的动态库,否则得把Paddle静态库链接到解释器里。
28+
* 解释性语言实际运行的二进制是解释器本身,如果调用静态库只能将静态库与解释器链接。例如对于Java来说,便是将静态库加入JVM中。这对于通常的Java的开发者来说,是不常见的做法。
29+
30+
### 动态库中不嵌入任何其他语言的解释器
31+
32+
* 目前Paddle的进程模型是C++内部驱动Python解释器进行模型配置解析和数据读取
33+
* 我们最终的动态库中不嵌入Python或者其他任何语言的解释器。模型配置解析,数据读取均交由其他语言完成
34+
35+
现阶段Paddle有一个问题是,Paddle内嵌的Python解释器和外部使用的Python如果版本不同,会直接报错退出。
36+
37+
### Paddle动态库中,不引用其他动态库
38+
39+
* 即这个动态库是不依赖于其他任何文件的,可以在任何机器上执行的。
40+
41+
### 这个动态库使用C99标准的头文件导出一些函数,不使用/导出C++符号
42+
43+
* 由于C++编译器没有[名字修饰](https://en.wikipedia.org/wiki/Name_mangling#C.2B.2B)的规范,不同版本的编译器之间,对于同一段C++代码生成的符号可能不一致。而多语言接口需要直接读取生成的二进制(动态库),需要有稳定的导出符号。
44+
* C语言是有导出符号的标准的,并且在常见的平台上,都是ABI调用标准的。
45+
* 大多数语言都支持使用C语言API
46+
* 使用C99而不使用C89,是因为C99支持[Fixed-width integer types](https://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types)[Boolean type](https://en.wikipedia.org/wiki/C_data_types#Boolean_type)
47+
* 使用C99而不使用C11的原因是,[C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision))并没有Paddle特别需要的特性,且C99相对于C11使用更加广泛。
48+
49+
### 不导出Paddle内部的结构体、类,仅仅使用`void*`指针作为类型的句柄(handler)
50+
51+
* Paddle内部的类为C++书写,直接导出到C的接口比较困难。
52+
* 在C-API中使用`void*`来表示Paddle内部类。再在每一个API中自己检查类型。
53+
54+
在C的头文件 `paddle_matrix.h` 中:
55+
56+
```C
57+
typedef void* paddle_matrix;
58+
typedef int paddle_error;
59+
60+
extern "C"
61+
paddle_error paddle_matrix_shape(paddle_matrix matrix,
62+
uint64_t* width,
63+
uint64_t* height);
64+
```
65+
而在CPP里面实现这个C的接口,文件 `paddle_matrix.cpp`
66+
67+
```cpp
68+
#include "paddle/math/matrix.hpp"
69+
extern "C"
70+
paddle_error paddle_matrix_shape(paddle_matrix matrix,
71+
uint64_t *width,
72+
uint64_t *height) {
73+
auto m = (paddle::math::matrix*)(matrix);
74+
*width = m->width();
75+
*height = m->height();
76+
}
77+
```
78+
79+
其中`paddle/math/matrix.hpp`文件内容为:
80+
81+
```cpp
82+
namespace paddle {
83+
namespace math {
84+
85+
class Matrix {
86+
//...
87+
};
88+
89+
} // namespace math
90+
} // namespace paddle
91+
```
92+
93+
### 不使用SWIG这种代码生成器,而是手写多语言绑定
94+
95+
* [SWIG](http://www.swig.org/)是一个多语言接口的代码生成器。他的目标是使用C/C++写代码,SWIG直接读取C/C++的头文件,生成各种语言的绑定代码。
96+
* 对于多语言接口,SWIG需要写一个interface文件。这个文件具有独特的语法,学习成本高。且增加一个第三方语言,就需要对这个第三方语言增加一些定义。有的时候,interface文件的写法非常[tricky](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/api/Paddle.swig#L36)。社区贡献代码学习成本高。
97+
* SWIG暴露的接口保留了C++的接口样式,很难保证多语言代码风格的一致性。(函数命名,错误处理)
98+
* 因为SWIG在第三方语言中暴露的函数名,类名和C++中完全一致。C++的命名风格并不能适应其他第三方语言。如果使用SWIG我们需要将在interface文件里,将大量的`SomeCppClass`重命名成`some_python_class`,或者`SomeGoTypes`。
99+
* 对于不同语言,错误处理的方式也不尽相同。例如对于Java或者Python,最常见的错误处理方式是Exception,而对于Golang,错误处理方式是返回值。而SWIG只能简单的暴露C++接口,无法做到对于各种语言错误处理方式的适配。
100+
* 对于大多数语言,直接使用C语言的.h并不困难。例如Python的[cffi](https://cffi.readthedocs.io/en/latest/overview.html#simple-example-abi-level-in-line)或者[Cython](http://cython.org/), golang的[cgo](https://golang.org/cmd/cgo/)。
101+
* SWIG支持的语言或者解释器有局限。例如对于Python,使用SWIG只支持CPython解释器,而不支持PyPy解释器。
102+
103+
104+
## 原因列表
105+
106+
| 结论 | 对比 | 原因 |
107+
|---| --- | --- |
108+
| 使用动态库 | 不使用静态库 | 解释型语言只能调用动态库,Paddle静态库链接复杂 |
109+
| 不嵌入其他语言解释器 | 不嵌入Python解释器 | Paddle C++目前嵌入Python解释器,会导致不同版本Python在一个进程里的bug |
110+
| 不引用其他动态库 | | Paddle一个动态库可以在任何Linux系统上运行 |
111+
| 使用C99做接口 | 不使用C++做接口 | C有标准的ABI,C99是目前C最广泛的使用标准,且C99支持bool类型和定长整数(uint64_t等)类型 |
112+
| 使用void*作为类句柄 | 不显示的写每个类具体包含什么| 实现简单,并且让接口脱离实现细节 |
113+
| 手写多语言绑定 | 不使用SWIG | 使用SWIG需要多语言绑定的开发人员熟练掌握SWIG配置,社区参与困难。SWIG生成的代码不能保证多语言代码风格的一致性 |
114+
115+
116+
## 简单实现
117+
118+
TBD

doc/getstarted/basic_usage/index_cn.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ PaddlePaddle是源于百度的一个深度学习平台。这份简短的介绍
5555
# 线性计算网络层: ȳ = wx + b
5656
ȳ = fc_layer(input=x, param_attr=ParamAttr(name='w'), size=1, act=LinearActivation(), bias_attr=ParamAttr(name='b'))
5757
# 计算误差函数,即 ȳ 和真实 y 之间的距离
58-
cost = regression_cost(input= ȳ, label=y)
58+
cost = mse_cost(input= ȳ, label=y)
5959
outputs(cost)
6060
6161
@@ -69,7 +69,7 @@ PaddlePaddle是源于百度的一个深度学习平台。这份简短的介绍
6969

7070
- **数据层**:数据层 `data_layer` 是神经网络的入口,它读入数据并将它们传输到接下来的网络层。这里数据层有两个,分别对应于变量 `x` 和 `y`。
7171
- **全连接层**:全连接层 `fc_layer` 是基础的计算单元,这里利用它建模变量之间的线性关系。计算单元是神经网络的核心,PaddlePaddle支持大量的计算单元和任意深度的网络连接,从而可以拟合任意的函数来学习复杂的数据关系。
72-
- **回归误差代价层**:回归误差代价层 `regression_cost` 是众多误差代价函数层的一种,它们在训练过程作为网络的出口,用来计算模型的误差,是模型参数优化的目标函数。
72+
- **回归误差代价层**:回归误差代价层 `mse_cost` 是众多误差代价函数层的一种,它们在训练过程作为网络的出口,用来计算模型的误差,是模型参数优化的目标函数。
7373

7474
定义了网络结构并保存为 `trainer_config.py` 之后,运行以下训练命令:
7575

doc/getstarted/basic_usage/index_en.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ To recover this relationship between ``X`` and ``Y``, we use a neural network wi
4949
x = data_layer(name='x', size=1)
5050
y = data_layer(name='y', size=1)
5151
y_predict = fc_layer(input=x, param_attr=ParamAttr(name='w'), size=1, act=LinearActivation(), bias_attr=ParamAttr(name='b'))
52-
cost = regression_cost(input=y_predict, label=y)
52+
cost = mse_cost(input=y_predict, label=y)
5353
outputs(cost)
5454
5555
Some of the most fundamental usages of PaddlePaddle are demonstrated:

0 commit comments

Comments
 (0)