Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.
The Interaction between Python and C++ can be simplified as two steps:
1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.
2. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ fo finish Op construction task.
### Message form C++ to Python
We define a Protobuf message class `OpProto` to hold message needed in the first step. What should an `OpProto` contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”
Following message are necessary:
1. Op's name, and its simple comment.
2. Input and output variable number; each variable's name, type, and comment.
3. Op's attributes; each attribute includes name, type, comment, **default value** and **value range**.
To hold message needed in the above second step, we define Protobuf message class `OpDesc`. It is used to hold user-specified parameters in Op describing.
```proto
message OpDesc {
required string type = 1;
repeated string inputs = 2;
repeated string outputs = 3;
map<string, AttrValue> attrs = 4;
};
```
## OpProto Register
Every Op has its own `OpProto`. For using convenience, we need to register them and record all their messages. For each `Op` class, we define a corresponding `OpMaker` class, in whose constructor we implement the `OpProto`'s building process. `OpMaker`'s constructor will be invoked by another function `OpRegistry::RegisterOp()`.
AddAttr("scale", "scale of cosine op", float).Default(1.0).LargerThan(0.0);
AddType("cos");
AddComment("This is cos op");
}
}
REGISTER_OP(CosineOp, CosineOpProtoMaker, cos);
```
In `REGISTER_OP(CosineOp, CosineOpProtoMaker, cos)`, we register not only `CosineOp` but also `CosineOpProto`. As fields of `CosineOpProto`, the default value and value range of `scale` are also registered here.
## Python API
Python APIs are divided into two types, high-level API and low-level API.
### High-Level API
High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs.
Here is a sample about how a define a fc layer:
```python
hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid");
```
`hd` is the output of `fc_layer` and it's a `variable`. It can be further sent into other layers as input.
The definition of `fc_layer()`:
```python
def fc_layer(input, size, with_bias, activation):
attr_map = {"size":size}
check_attrs(attr_map)
w = make_variable('w')
if with_bias:
b = make_variable('b')
else:
b = None
fc_output = make_variable('fc_output');
fc_op(input, w, b, fc_output, attr_map)
act_output = make_variable('sigmod_output');
if activation == "sigmod":
sigmod_op(fc_output, act_output);
elif:
# ...
return act_output;
```
### Low Leval API
In above sample, `fc_op` and `sigmod_op` are low-level API. They build `OpDesc` and invoke corresponding C++ code.
<liclass="toctree-l2"><aclass="reference internal"href="../getstarted/build_and_install/index_en.html">Install and Build</a><ul>
<liclass="toctree-l3"><aclass="reference internal"href="../getstarted/build_and_install/docker_install_en.html">PaddlePaddle in Docker Containers</a></li>
<liclass="toctree-l2"><aclass="reference internal"href="../howto/usage/k8s/k8s_en.html">Paddle On Kubernetes</a></li>
<liclass="toctree-l2"><aclass="reference internal"href="../howto/usage/k8s/k8s_aws_en.html">Distributed PaddlePaddle Training on AWS with Kubernetes</a></li>
<liclass="toctree-l2"><aclass="reference internal"href="../howto/dev/new_layer_en.html">Write New Layers</a></li>
<spanid="interaction-between-c-and-python"></span><h1>Interaction between C++ and Python<aclass="headerlink"href="#interaction-between-c-and-python"title="Permalink to this headline">¶</a></h1>
<p>Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.</p>
<p>The Interaction between Python and C++ can be simplified as two steps:</p>
<olclass="simple">
<li>C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.</li>
<li>Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ fo finish Op construction task.</li>
</ol>
<divclass="section"id="message-form-c-to-python">
<spanid="message-form-c-to-python"></span><h2>Message form C++ to Python<aclass="headerlink"href="#message-form-c-to-python"title="Permalink to this headline">¶</a></h2>
<p>We define a Protobuf message class <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> to hold message needed in the first step. What should an <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”</p>
<p>Following message are necessary:</p>
<olclass="simple">
<li>Op’s name, and its simple comment.</li>
<li>Input and output variable number; each variable’s name, type, and comment.</li>
<li>Op’s attributes; each attribute includes name, type, comment, <strong>default value</strong> and <strong>value range</strong>.</li>
</ol>
<p>So <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> can be defined as follows:</p>
<spanid="message-from-python-to-c"></span><h2>Message from Python to C++<aclass="headerlink"href="#message-from-python-to-c"title="Permalink to this headline">¶</a></h2>
<p>To hold message needed in the above second step, we define Protobuf message class <codeclass="docutils literal"><spanclass="pre">OpDesc</span></code>. It is used to hold user-specified parameters in Op describing.</p>
<spanid="opproto-register"></span><h1>OpProto Register<aclass="headerlink"href="#opproto-register"title="Permalink to this headline">¶</a></h1>
<p>Every Op has its own <codeclass="docutils literal"><spanclass="pre">OpProto</span></code>. For using convenience, we need to register them and record all their messages. For each <codeclass="docutils literal"><spanclass="pre">Op</span></code> class, we define a corresponding <codeclass="docutils literal"><spanclass="pre">OpMaker</span></code> class, in whose constructor we implement the <codeclass="docutils literal"><spanclass="pre">OpProto</span></code>‘s building process. <codeclass="docutils literal"><spanclass="pre">OpMaker</span></code>‘s constructor will be invoked by another function <codeclass="docutils literal"><spanclass="pre">OpRegistry::RegisterOp()</span></code>.</p>
<spanclass="n">AddInput</span><spanclass="p">(</span><spanclass="s">"input"</span><spanclass="p">,</span><spanclass="s">"input of cosine op"</span><spanclass="p">);</span>
<spanclass="n">AddAttr</span><spanclass="p">(</span><spanclass="s">"scale"</span><spanclass="p">,</span><spanclass="s">"scale of cosine op"</span><spanclass="p">,</span><spanclass="kt">float</span><spanclass="p">).</span><spanclass="n">Default</span><spanclass="p">(</span><spanclass="mf">1.0</span><spanclass="p">).</span><spanclass="n">LargerThan</span><spanclass="p">(</span><spanclass="mf">0.0</span><spanclass="p">);</span>
<p>In <codeclass="docutils literal"><spanclass="pre">REGISTER_OP(CosineOp,</span><spanclass="pre">CosineOpProtoMaker,</span><spanclass="pre">cos)</span></code>, we register not only <codeclass="docutils literal"><spanclass="pre">CosineOp</span></code> but also <codeclass="docutils literal"><spanclass="pre">CosineOpProto</span></code>. As fields of <codeclass="docutils literal"><spanclass="pre">CosineOpProto</span></code>, the default value and value range of <codeclass="docutils literal"><spanclass="pre">scale</span></code> are also registered here.</p>
</div>
<divclass="section"id="python-api">
<spanid="python-api"></span><h1>Python API<aclass="headerlink"href="#python-api"title="Permalink to this headline">¶</a></h1>
<p>Python APIs are divided into two types, high-level API and low-level API.</p>
<divclass="section"id="high-level-api">
<spanid="high-level-api"></span><h2>High-Level API<aclass="headerlink"href="#high-level-api"title="Permalink to this headline">¶</a></h2>
<p>High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs.</p>
<p>Here is a sample about how a define a fc layer:</p>
<p><codeclass="docutils literal"><spanclass="pre">hd</span></code> is the output of <codeclass="docutils literal"><spanclass="pre">fc_layer</span></code> and it’s a <codeclass="docutils literal"><spanclass="pre">variable</span></code>. It can be further sent into other layers as input.</p>
<p>The definition of <codeclass="docutils literal"><spanclass="pre">fc_layer()</span></code>:</p>
<spanid="low-leval-api"></span><h2>Low Leval API<aclass="headerlink"href="#low-leval-api"title="Permalink to this headline">¶</a></h2>
<p>In above sample, <codeclass="docutils literal"><spanclass="pre">fc_op</span></code> and <codeclass="docutils literal"><spanclass="pre">sigmod_op</span></code> are low-level API. They build <codeclass="docutils literal"><spanclass="pre">OpDesc</span></code> and invoke corresponding C++ code.</p>
Built with <ahref="http://sphinx-doc.org/">Sphinx</a> using a <ahref="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <ahref="https://readthedocs.org">Read the Docs</a>.
Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.
The Interaction between Python and C++ can be simplified as two steps:
1. C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.
2. Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ fo finish Op construction task.
### Message form C++ to Python
We define a Protobuf message class `OpProto` to hold message needed in the first step. What should an `OpProto` contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”
Following message are necessary:
1. Op's name, and its simple comment.
2. Input and output variable number; each variable's name, type, and comment.
3. Op's attributes; each attribute includes name, type, comment, **default value** and **value range**.
To hold message needed in the above second step, we define Protobuf message class `OpDesc`. It is used to hold user-specified parameters in Op describing.
```proto
message OpDesc {
required string type = 1;
repeated string inputs = 2;
repeated string outputs = 3;
map<string, AttrValue> attrs = 4;
};
```
## OpProto Register
Every Op has its own `OpProto`. For using convenience, we need to register them and record all their messages. For each `Op` class, we define a corresponding `OpMaker` class, in whose constructor we implement the `OpProto`'s building process. `OpMaker`'s constructor will be invoked by another function `OpRegistry::RegisterOp()`.
AddAttr("scale", "scale of cosine op", float).Default(1.0).LargerThan(0.0);
AddType("cos");
AddComment("This is cos op");
}
}
REGISTER_OP(CosineOp, CosineOpProtoMaker, cos);
```
In `REGISTER_OP(CosineOp, CosineOpProtoMaker, cos)`, we register not only `CosineOp` but also `CosineOpProto`. As fields of `CosineOpProto`, the default value and value range of `scale` are also registered here.
## Python API
Python APIs are divided into two types, high-level API and low-level API.
### High-Level API
High-level API is called by users directly, so it should keep its style consistent with existing V2 APIs.
Here is a sample about how a define a fc layer:
```python
hd = fc_layer(input=data, size=56, with_bias=True, activation="sigmoid");
```
`hd` is the output of `fc_layer` and it's a `variable`. It can be further sent into other layers as input.
The definition of `fc_layer()`:
```python
def fc_layer(input, size, with_bias, activation):
attr_map = {"size":size}
check_attrs(attr_map)
w = make_variable('w')
if with_bias:
b = make_variable('b')
else:
b = None
fc_output = make_variable('fc_output');
fc_op(input, w, b, fc_output, attr_map)
act_output = make_variable('sigmod_output');
if activation == "sigmod":
sigmod_op(fc_output, act_output);
elif:
# ...
return act_output;
```
### Low Leval API
In above sample, `fc_op` and `sigmod_op` are low-level API. They build `OpDesc` and invoke corresponding C++ code.
<spanid="interaction-between-c-and-python"></span><h1>Interaction between C++ and Python<aclass="headerlink"href="#interaction-between-c-and-python"title="永久链接至标题">¶</a></h1>
<p>Users employ API in Python to describe their own network, however, the network construction actually happens in C++. so Protobuf is introduced to send the message between Python and C++.</p>
<p>The Interaction between Python and C++ can be simplified as two steps:</p>
<olclass="simple">
<li>C++ tells Python how many Ops there are, and what parameter do users need to offer to initialize a new Op. Python then builds API for each Op at compile time.</li>
<li>Users invoke APIs built by Python and provide necessary parameters. These parameters will be sent to C++ fo finish Op construction task.</li>
</ol>
<divclass="section"id="message-form-c-to-python">
<spanid="message-form-c-to-python"></span><h2>Message form C++ to Python<aclass="headerlink"href="#message-form-c-to-python"title="永久链接至标题">¶</a></h2>
<p>We define a Protobuf message class <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> to hold message needed in the first step. What should an <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> contain? This question is equivalent to “What message do we need to offer, to build a Python API which is legal and user oriented and can use to describe a whole Op.”</p>
<p>Following message are necessary:</p>
<olclass="simple">
<li>Op’s name, and its simple comment.</li>
<li>Input and output variable number; each variable’s name, type, and comment.</li>
<li>Op’s attributes; each attribute includes name, type, comment, <strong>default value</strong> and <strong>value range</strong>.</li>
</ol>
<p>So <codeclass="docutils literal"><spanclass="pre">OpProto</span></code> can be defined as follows:</p>
<spanid="message-from-python-to-c"></span><h2>Message from Python to C++<aclass="headerlink"href="#message-from-python-to-c"title="永久链接至标题">¶</a></h2>
<p>To hold message needed in the above second step, we define Protobuf message class <codeclass="docutils literal"><spanclass="pre">OpDesc</span></code>. It is used to hold user-specified parameters in Op describing.</p>
<p>Every Op has its own <codeclass="docutils literal"><spanclass="pre">OpProto</span></code>. For using convenience, we need to register them and record all their messages. For each <codeclass="docutils literal"><spanclass="pre">Op</span></code> class, we define a corresponding <codeclass="docutils literal"><spanclass="pre">OpMaker</span></code> class, in whose constructor we implement the <codeclass="docutils literal"><spanclass="pre">OpProto</span></code>‘s building process. <codeclass="docutils literal"><spanclass="pre">OpMaker</span></code>‘s constructor will be invoked by another function <codeclass="docutils literal"><spanclass="pre">OpRegistry::RegisterOp()</span></code>.</p>
<spanclass="n">AddInput</span><spanclass="p">(</span><spanclass="s">"input"</span><spanclass="p">,</span><spanclass="s">"input of cosine op"</span><spanclass="p">);</span>
<spanclass="n">AddAttr</span><spanclass="p">(</span><spanclass="s">"scale"</span><spanclass="p">,</span><spanclass="s">"scale of cosine op"</span><spanclass="p">,</span><spanclass="kt">float</span><spanclass="p">).</span><spanclass="n">Default</span><spanclass="p">(</span><spanclass="mf">1.0</span><spanclass="p">).</span><spanclass="n">LargerThan</span><spanclass="p">(</span><spanclass="mf">0.0</span><spanclass="p">);</span>
<p>In <codeclass="docutils literal"><spanclass="pre">REGISTER_OP(CosineOp,</span><spanclass="pre">CosineOpProtoMaker,</span><spanclass="pre">cos)</span></code>, we register not only <codeclass="docutils literal"><spanclass="pre">CosineOp</span></code> but also <codeclass="docutils literal"><spanclass="pre">CosineOpProto</span></code>. As fields of <codeclass="docutils literal"><spanclass="pre">CosineOpProto</span></code>, the default value and value range of <codeclass="docutils literal"><spanclass="pre">scale</span></code> are also registered here.</p>
<p><codeclass="docutils literal"><spanclass="pre">hd</span></code> is the output of <codeclass="docutils literal"><spanclass="pre">fc_layer</span></code> and it’s a <codeclass="docutils literal"><spanclass="pre">variable</span></code>. It can be further sent into other layers as input.</p>
<p>The definition of <codeclass="docutils literal"><spanclass="pre">fc_layer()</span></code>:</p>
<p>In above sample, <codeclass="docutils literal"><spanclass="pre">fc_op</span></code> and <codeclass="docutils literal"><spanclass="pre">sigmod_op</span></code> are low-level API. They build <codeclass="docutils literal"><spanclass="pre">OpDesc</span></code> and invoke corresponding C++ code.</p>
Built with <ahref="http://sphinx-doc.org/">Sphinx</a> using a <ahref="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <ahref="https://readthedocs.org">Read the Docs</a>.