Here are the base types needed. For details, please refer to the design docs.
Here are the base types needed. For details, please refer to the design docs.
...
@@ -232,4 +235,122 @@ The system will automatically bind to Python and link it to a generated library.
...
@@ -232,4 +235,122 @@ The system will automatically bind to Python and link it to a generated library.
## Unit Tests
## Unit Tests
Unit tests include comparing a forward operator's implementations on different devices, comparing a backward operator's implementation on different devices, and a scaling test for the backward operator. Here, we introduce the [unit tests for `MulOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py).
Unit tests for an operator include
1. comparing a forward operator's implementations on different devices,
2. comparing a backward operator's implementation on different devices, and
3. a scaling test for the backward operator.
Here, we introduce the [unit tests for `MulOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py).
### Testing Forward Operators
A forward operator unit test inherits `unittest.TestCase` and defines metaclass `__metaclass__ = OpTestMeta`. More concrete tests are performed in `OpTestMeta`. Testing a forward operator requires the following:
1. Defining input, output and relevant attributes in `setUp` method.
2. Generating random input data.
3. Implementing the same computation logic in a Python script:
```python
import unittest
import numpy as np
from gradient_checker import GradientChecker, create_op
Get its output, and compare it with the forward operator's own output.
The code above first loads required packages. In addition, we have
- `self.type = "mul" ` defines the type that is identical to what the operator's registered type.
- `self.inputs` defines input, with type `numpy.array` and initializes it.
- `self.outputs` defines output and completes the same operator computation in the Python script, and returns its result from the Python script.
### Testing Backward Operators
A backward operator unit test inherits `GradientChecker`, which inherits `unittest.TestCase`. As a result, **a backward operator unit test needs to be have the prefix `test_`**.
- `create_op("mul")` creates the backward operator's corresponding forward operator.
- `compare_grad` compares results between utilizing the CPU and the GPU.
- `test_normal` calls `check_grad` to validate scaling tests' correctness and stability through numeric methods.
- The first variable `self.op` denotes the forward operator.
- The second variable `self.inputs` denotes the input dictionary, which has its key value identical to its `ProtoMaker` definitions.
- The third variable `["X", "Y"]` appoints `X` and `Y` to be scale tested.
- The fourth variable `"Out"` points to the network's final output target `Out`.
- `test_ignore_x` and `test_ignore_y`branches test the cases where there is only one scaling input.
### Compiling and Running
Any new unit testing file of the format `test_*.py` added to the director `python/paddle/v2/framework/tests` is automatically added to the project to compile.
Note that **unlike the compile test for Ops, running unit tests requires compiling the entire project** and requires compiling with flag `WITH_TESTING` on i.e. `cmake paddle_dir -DWITH_TESTING=ON`.
After successfully compiling the project, run the following command to run unit tests:
```bash
make test ARGS="-R test_mul_op -V"
```
Or,
```bash
ctest -R test_mul_op
```
## Remarks
- Every `*_op.h` (if applicable), `*_op.cc`, and `*_op.cu` (if applicable) must be created for a unique Op. Compiling will fail if multiple operators are included per file.
- The type with which an operator is registered needs to be identical to the Op's name. Registering `REGISTER_OP(B, ...)` in `A_op.cc` will cause unit testing failures.
- If the operator does not implement a GPU kernel, please refrain from creating an empty `*_op.cu` file, or else unit tests will fail.
- If multiple operators rely on some shared methods, a file NOT named `*_op.*` can be created to store them, such as `gather.h`.
<spanid="how-to-write-a-new-operator"></span><h1>How to write a new operator<aclass="headerlink"href="#how-to-write-a-new-operator"title="Permalink to this headline">¶</a></h1>
<spanid="how-to-write-a-new-operator"></span><h1>How to write a new operator<aclass="headerlink"href="#how-to-write-a-new-operator"title="Permalink to this headline">¶</a></h1>
<spanid="background"></span><h2>Background<aclass="headerlink"href="#background"title="Permalink to this headline">¶</a></h2>
<spanid="background"></span><h2>Background<aclass="headerlink"href="#background"title="Permalink to this headline">¶</a></h2>
...
@@ -388,7 +394,118 @@ Registering the Op | Ops are registered in <code class="docutils liter
...
@@ -388,7 +394,118 @@ Registering the Op | Ops are registered in <code class="docutils liter
</div>
</div>
<divclass="section"id="unit-tests">
<divclass="section"id="unit-tests">
<spanid="unit-tests"></span><h2>Unit Tests<aclass="headerlink"href="#unit-tests"title="Permalink to this headline">¶</a></h2>
<spanid="unit-tests"></span><h2>Unit Tests<aclass="headerlink"href="#unit-tests"title="Permalink to this headline">¶</a></h2>
<p>Unit tests include comparing a forward operator’s implementations on different devices, comparing a backward operator’s implementation on different devices, and a scaling test for the backward operator. Here, we introduce the <aclass="reference external"href="https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py">unit tests for <codeclass="docutils literal"><spanclass="pre">MulOp</span></code></a>.</p>
<p>Unit tests for an operator include</p>
<olclass="simple">
<li>comparing a forward operator’s implementations on different devices,</li>
<li>comparing a backward operator’s implementation on different devices, and</li>
<li>a scaling test for the backward operator.</li>
</ol>
<p>Here, we introduce the <aclass="reference external"href="https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/tests/test_mul_op.py">unit tests for <codeclass="docutils literal"><spanclass="pre">MulOp</span></code></a>.</p>
<spanid="testing-forward-operators"></span><h3>Testing Forward Operators<aclass="headerlink"href="#testing-forward-operators"title="Permalink to this headline">¶</a></h3>
<p>A forward operator unit test inherits <codeclass="docutils literal"><spanclass="pre">unittest.TestCase</span></code> and defines metaclass <codeclass="docutils literal"><spanclass="pre">__metaclass__</span><spanclass="pre">=</span><spanclass="pre">OpTestMeta</span></code>. More concrete tests are performed in <codeclass="docutils literal"><spanclass="pre">OpTestMeta</span></code>. Testing a forward operator requires the following:</p>
<olclass="simple">
<li>Defining input, output and relevant attributes in <codeclass="docutils literal"><spanclass="pre">setUp</span></code> method.</li>
<li>Generating random input data.</li>
<li>Implementing the same computation logic in a Python script:</li>
<p>Get its output, and compare it with the forward operator’s own output.</p>
<p>The code above first loads required packages. In addition, we have</p>
<ulclass="simple">
<li><codeclass="docutils literal"><spanclass="pre">self.type</span><spanclass="pre">=</span><spanclass="pre">"mul"</span></code> defines the type that is identical to what the operator’s registered type.</li>
<li><codeclass="docutils literal"><spanclass="pre">self.inputs</span></code> defines input, with type <codeclass="docutils literal"><spanclass="pre">numpy.array</span></code> and initializes it.</li>
<li><codeclass="docutils literal"><spanclass="pre">self.outputs</span></code> defines output and completes the same operator computation in the Python script, and returns its result from the Python script.</li>
<spanid="testing-backward-operators"></span><h3>Testing Backward Operators<aclass="headerlink"href="#testing-backward-operators"title="Permalink to this headline">¶</a></h3>
<p>A backward operator unit test inherits <codeclass="docutils literal"><spanclass="pre">GradientChecker</span></code>, which inherits <codeclass="docutils literal"><spanclass="pre">unittest.TestCase</span></code>. As a result, <strong>a backward operator unit test needs to be have the prefix <codeclass="docutils literal"><spanclass="pre">test_</span></code></strong>.</p>
<li><codeclass="docutils literal"><spanclass="pre">create_op("mul")</span></code> creates the backward operator’s corresponding forward operator.</li>
<li><codeclass="docutils literal"><spanclass="pre">compare_grad</span></code> compares results between utilizing the CPU and the GPU.</li>
<li><codeclass="docutils literal"><spanclass="pre">test_normal</span></code> calls <codeclass="docutils literal"><spanclass="pre">check_grad</span></code> to validate scaling tests’ correctness and stability through numeric methods.<ul>
<li>The first variable <codeclass="docutils literal"><spanclass="pre">self.op</span></code> denotes the forward operator.</li>
<li>The second variable <codeclass="docutils literal"><spanclass="pre">self.inputs</span></code> denotes the input dictionary, which has its key value identical to its <codeclass="docutils literal"><spanclass="pre">ProtoMaker</span></code> definitions.</li>
<li>The third variable <codeclass="docutils literal"><spanclass="pre">["X",</span><spanclass="pre">"Y"]</span></code> appoints <codeclass="docutils literal"><spanclass="pre">X</span></code> and <codeclass="docutils literal"><spanclass="pre">Y</span></code> to be scale tested.</li>
<li>The fourth variable <codeclass="docutils literal"><spanclass="pre">"Out"</span></code> points to the network’s final output target <codeclass="docutils literal"><spanclass="pre">Out</span></code>.</li>
</ul>
</li>
<li><codeclass="docutils literal"><spanclass="pre">test_ignore_x</span></code> and <codeclass="docutils literal"><spanclass="pre">test_ignore_y</span></code>branches test the cases where there is only one scaling input.</li>
</ul>
</div>
<divclass="section"id="compiling-and-running">
<spanid="compiling-and-running"></span><h3>Compiling and Running<aclass="headerlink"href="#compiling-and-running"title="Permalink to this headline">¶</a></h3>
<p>Any new unit testing file of the format <codeclass="docutils literal"><spanclass="pre">test_*.py</span></code> added to the director <codeclass="docutils literal"><spanclass="pre">python/paddle/v2/framework/tests</span></code> is automatically added to the project to compile.</p>
<p>Note that <strong>unlike the compile test for Ops, running unit tests requires compiling the entire project</strong> and requires compiling with flag <codeclass="docutils literal"><spanclass="pre">WITH_TESTING</span></code> on i.e. <codeclass="docutils literal"><spanclass="pre">cmake</span><spanclass="pre">paddle_dir</span><spanclass="pre">-DWITH_TESTING=ON</span></code>.</p>
<p>After successfully compiling the project, run the following command to run unit tests:</p>
<spanid="remarks"></span><h2>Remarks<aclass="headerlink"href="#remarks"title="Permalink to this headline">¶</a></h2>
<ulclass="simple">
<li>Every <codeclass="docutils literal"><spanclass="pre">*_op.h</span></code> (if applicable), <codeclass="docutils literal"><spanclass="pre">*_op.cc</span></code>, and <codeclass="docutils literal"><spanclass="pre">*_op.cu</span></code> (if applicable) must be created for a unique Op. Compiling will fail if multiple operators are included per file.</li>
<li>The type with which an operator is registered needs to be identical to the Op’s name. Registering <codeclass="docutils literal"><spanclass="pre">REGISTER_OP(B,</span><spanclass="pre">...)</span></code> in <codeclass="docutils literal"><spanclass="pre">A_op.cc</span></code> will cause unit testing failures.</li>
<li>If the operator does not implement a GPU kernel, please refrain from creating an empty <codeclass="docutils literal"><spanclass="pre">*_op.cu</span></code> file, or else unit tests will fail.</li>
<li>If multiple operators rely on some shared methods, a file NOT named <codeclass="docutils literal"><spanclass="pre">*_op.*</span></code> can be created to store them, such as <codeclass="docutils literal"><spanclass="pre">gather.h</span></code>.</li>