arm_compute v19.08
diff --git a/documentation/add_operator.xhtml b/documentation/add_operator.xhtml
index 4395a6c..a0ea802 100644
--- a/documentation/add_operator.xhtml
+++ b/documentation/add_operator.xhtml
@@ -40,7 +40,7 @@
<img alt="Compute Library" src="https://raw.githubusercontent.com/ARM-software/ComputeLibrary/gh-pages/ACL_logo.png" style="max-width: 100%;margin-top: 15px;margin-left: 10px"/>
<td style="padding-left: 0.5em;">
<div id="projectname">
-  <span id="projectnumber">19.05</span>
+  <span id="projectnumber">19.08</span>
</div>
</td>
</tr>
@@ -141,7 +141,7 @@
<p>If an operator handles a new datatype, it must be added to the library. While adding a new data type to the library, it's necessary to implement the function to enable printing, the <a class="el" href="namespacearm__compute.xhtml#ab75d8ff29ba9b398d5740b3efd156e71" title="Formatted output of the GradientDimension type.">to_string()</a> method and the output stream insertion (<<) operator. Every datatype implements these two functions in <a class="el" href="utils_2_type_printer_8h.xhtml">utils/TypePrinter.h</a></p>
<p>A quick example, in <a href="https://github.com/ARM-software/ComputeLibrary/blob/master/arm_compute/core/Types.h">Types.h</a> we add:</p>
<div class="fragment"><div class="line"></div><div class="line"><span class="keyword">enum class</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0">DataLayout</a></div><div class="line">{</div><div class="line"> <a class="code" href="namespacearm__compute.xhtml#a3a440b3893fa10608d4428958be1c52ea696b031073e74bf2cb98e5ef201d4aa3">UNKNOWN</a>, </div><div class="line"> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0a6b99f356fe3b30a2a850b5ea897c289f">NCHW</a>, </div><div class="line"> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0ad066db54b89b0912e7e7c6da51e2da51">NHWC</a> </div><div class="line">};</div></div><!-- fragment --><p> And for printing:</p>
-<div class="fragment"><div class="line"></div><div class="line">inline ::std::ostream &<a class="code" href="namespacearm__compute.xhtml#af3985189d478b45014e7dead9d002e2a">operator<<</a>(::std::ostream &os, <span class="keyword">const</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0">DataLayout</a> &data_layout)</div><div class="line">{</div><div class="line"> <span class="keywordflow">switch</span>(data_layout)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#a3a440b3893fa10608d4428958be1c52ea696b031073e74bf2cb98e5ef201d4aa3">DataLayout::UNKNOWN</a>:</div><div class="line"> os << <span class="stringliteral">"UNKNOWN"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0ad066db54b89b0912e7e7c6da51e2da51">DataLayout::NHWC</a>:</div><div class="line"> os << <span class="stringliteral">"NHWC"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0a6b99f356fe3b30a2a850b5ea897c289f">DataLayout::NCHW</a>:</div><div class="line"> os << <span class="stringliteral">"NCHW"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">default</span>:</div><div class="line"> <a class="code" href="_error_8h.xhtml#a05b19c75afe9c24200a62b9724734bbd">ARM_COMPUTE_ERROR</a>(<span class="stringliteral">"NOT_SUPPORTED!"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> os;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">inline</span> std::string <a class="code" href="namespacearm__compute.xhtml#ab75d8ff29ba9b398d5740b3efd156e71">to_string</a>(<span class="keyword">const</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0">arm_compute::DataLayout</a> &data_layout)</div><div class="line">{</div><div class="line"> std::stringstream str;</div><div class="line"> str << data_layout;</div><div class="line"> <span class="keywordflow">return</span> str.str();</div><div class="line">}</div></div><!-- fragment --><p> In the ACL library, we use namespaces to group all the operators, functions, classes and interfaces. The main namespace to use is <a class="el" href="namespacearm__compute.xhtml" title="Copyright (c) 2017-2018 ARM Limited.">arm_compute</a>. In the test suite, the test framework and the individual tests use nested namespaces like <a class="el" href="namespacearm__compute_1_1test_1_1validation.xhtml">test::validation</a> or <a class="el" href="namespacearm__compute_1_1test_1_1benchmark.xhtml">test::benchmark</a> to group the different purposes of various parts of the suite. Utility functions like conversion or type cast operators, that are shared by multiple operators are in <a class="el" href="arm__compute_2core_2_utils_8h.xhtml">arm_compute/core/Utils.h</a>. Non-inlined function definitions go in the corresponding .cpp files in the src folder. Similarly, all common functions that process shapes, like calculating output shapes of an operator or shape conversions etc are in <a class="el" href="_shape_calculator_8h.xhtml">arm_compute/core/utils/misc/ShapeCalculator.h</a>.</p>
+<div class="fragment"><div class="line"></div><div class="line">inline ::std::ostream &<a class="code" href="namespacearm__compute.xhtml#af3985189d478b45014e7dead9d002e2a">operator<<</a>(::std::ostream &os, <span class="keyword">const</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0">DataLayout</a> &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#acf5f12bbab64dd614bd8220c97fe484f">data_layout</a>)</div><div class="line">{</div><div class="line"> <span class="keywordflow">switch</span>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#acf5f12bbab64dd614bd8220c97fe484f">data_layout</a>)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#a3a440b3893fa10608d4428958be1c52ea696b031073e74bf2cb98e5ef201d4aa3">DataLayout::UNKNOWN</a>:</div><div class="line"> os << <span class="stringliteral">"UNKNOWN"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0ad066db54b89b0912e7e7c6da51e2da51">DataLayout::NHWC</a>:</div><div class="line"> os << <span class="stringliteral">"NHWC"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">case</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0a6b99f356fe3b30a2a850b5ea897c289f">DataLayout::NCHW</a>:</div><div class="line"> os << <span class="stringliteral">"NCHW"</span>;</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">default</span>:</div><div class="line"> <a class="code" href="_error_8h.xhtml#a05b19c75afe9c24200a62b9724734bbd">ARM_COMPUTE_ERROR</a>(<span class="stringliteral">"NOT_SUPPORTED!"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> os;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">inline</span> std::string <a class="code" href="namespacearm__compute.xhtml#ab75d8ff29ba9b398d5740b3efd156e71">to_string</a>(<span class="keyword">const</span> <a class="code" href="namespacearm__compute.xhtml#ad1d5cce2d9e9a5d61c243e5c989112e0">arm_compute::DataLayout</a> &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#acf5f12bbab64dd614bd8220c97fe484f">data_layout</a>)</div><div class="line">{</div><div class="line"> std::stringstream str;</div><div class="line"> str << <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#acf5f12bbab64dd614bd8220c97fe484f">data_layout</a>;</div><div class="line"> <span class="keywordflow">return</span> str.str();</div><div class="line">}</div></div><!-- fragment --><p> In the ACL library, we use namespaces to group all the operators, functions, classes and interfaces. The main namespace to use is <a class="el" href="namespacearm__compute.xhtml" title="Copyright (c) 2017-2018 ARM Limited.">arm_compute</a>. In the test suite, the test framework and the individual tests use nested namespaces like <a class="el" href="namespacearm__compute_1_1test_1_1validation.xhtml">test::validation</a> or <a class="el" href="namespacearm__compute_1_1test_1_1benchmark.xhtml">test::benchmark</a> to group the different purposes of various parts of the suite. Utility functions like conversion or type cast operators, that are shared by multiple operators are in <a class="el" href="arm__compute_2core_2_utils_8h.xhtml">arm_compute/core/Utils.h</a>. Non-inlined function definitions go in the corresponding .cpp files in the src folder. Similarly, all common functions that process shapes, like calculating output shapes of an operator or shape conversions etc are in <a class="el" href="_shape_calculator_8h.xhtml">arm_compute/core/utils/misc/ShapeCalculator.h</a>.</p>
<h2><a class="anchor" id="S4_1_2_add_kernel"></a>
Add a kernel</h2>
<p>As we mentioned at the beginning, the kernel is the implementation of the operator or algorithm partially using a specific programming language related to the backend we want to use. Adding a kernel in the library means implementing the algorithm in a SIMD technology like NEON or OpenCL. All kernels in ACL must implement a common interface <a class="el" href="classarm__compute_1_1_i_kernel.xhtml" title="Common information for all the kernels.">IKernel</a> or one of the specific subinterfaces. <a class="el" href="classarm__compute_1_1_i_kernel.xhtml" title="Common information for all the kernels.">IKernel</a> is the common interface for all the kernels in the core library, it contains the main methods for configure and run the kernel itself, such as window() that return the maximum window the kernel can be executed on or is_parallelisable() for indicate whether or not the kernel is parallelizable. If the kernel is parallelizable then the window returned by the window() method can be split into sub-windows which can then be run in parallel, in the other case, only the window returned by window() can be passed to the run method. There are specific interfaces for OpenCL and Neon: <a class="el" href="classarm__compute_1_1_i_c_l_kernel.xhtml">ICLKernel</a>, INEKernel (using INEKernel = <a class="el" href="classarm__compute_1_1_i_c_p_p_kernel.xhtml">ICPPKernel</a>).</p>
@@ -187,7 +187,7 @@
</ul>
<p><a class="el" href="classarm__compute_1_1_c_p_p_scheduler.xhtml#a8d6828523921b7f9313f64c48550617f">CPPScheduler::schedule</a> provides a sample implementation that is used for NEON kernels. Memory management is the other aspect that the runtime layer is supposed to handle. Memory management of the tensors is abstracted using <a class="el" href="classarm__compute_1_1_tensor_allocator.xhtml" title="Basic implementation of a CPU memory tensor allocator.">TensorAllocator</a>. Each tensor holds a pointer to a <a class="el" href="classarm__compute_1_1_tensor_allocator.xhtml" title="Basic implementation of a CPU memory tensor allocator.">TensorAllocator</a> object, which is used to allocate and free the memory at runtime. The implementation that is currently supported in ACL allows memory blocks, required to be fulfilled for a given operator, to be grouped together under a <a class="el" href="namespacearm__compute.xhtml#a0e7a03e2e133cb1fbb12517a3f646a09">MemoryGroup</a>. Each group can be acquired and released. The underlying implementation of memory groups vary depending on whether NEON or CL is used. The memory group class uses memory pool to provide the required memory. It also uses the memory manager to manage the lifetime and a <a class="el" href="classarm__compute_1_1_i_pool_manager.xhtml" title="Memory pool manager interface.">IPoolManager</a> to manage the memory pools registered with the memory manager.</p>
<p>We have seen the various interfaces for a kernel in the core library, the same structure the same file structure design exists in the runtime module. <a class="el" href="classarm__compute_1_1_i_function.xhtml" title="Base class for all functions.">IFunction</a> is the base class for all the functions, it has two child interfaces: <a class="el" href="classarm__compute_1_1_i_c_l_simple_function.xhtml" title="Basic interface for functions which have a single OpenCL kernel.">ICLSimpleFunction</a> and <a class="el" href="classarm__compute_1_1_i_n_e_simple_function.xhtml" title="Basic interface for functions which have a single NEON kernel.">INESimpleFunction</a> that are used as base class for functions which call a single kernel.</p>
-<p>The new operator has to implement validate(), configure() and run(), these methods will call the respective function in the kernel considering that the multi-threading is used for the kernels which are parallelizable, by default std::thread::hardware_concurrency() threads are used. For NEON function can be used <a class="el" href="classarm__compute_1_1_c_p_p_scheduler.xhtml#ae64eebaa07f4d2da6cc2ba538c3cb095" title="Sets the number of threads the scheduler will use to run the kernels.">CPPScheduler::set_num_threads()</a> to manually set the number of threads, whereas for OpenCL kernels all the kernels are enqueued on the queue associated with <a class="el" href="classarm__compute_1_1_c_l_scheduler.xhtml" title="Provides global access to a CL context and command queue.">CLScheduler</a> and the queue is then flushed. For the runtime functions, there is an extra method implemented: prepare(), this method prepares the function for the run, it does all the heavy operations that are done only once (reshape the weight, release the memory not necessary after the reshape, etc). The prepare method can be called standalone or in the first run, if not called before, after then the function will be marked as prepared. The files we add are:</p>
+<p>The new operator has to implement validate(), configure() and <a class="el" href="namespacearm__compute_1_1test_1_1validation.xhtml#aae8f98973dd49e5afd7309bb34d4e3c3">run()</a>, these methods will call the respective function in the kernel considering that the multi-threading is used for the kernels which are parallelizable, by default std::thread::hardware_concurrency() threads are used. For NEON function can be used <a class="el" href="classarm__compute_1_1_c_p_p_scheduler.xhtml#ae64eebaa07f4d2da6cc2ba538c3cb095" title="Sets the number of threads the scheduler will use to run the kernels.">CPPScheduler::set_num_threads()</a> to manually set the number of threads, whereas for OpenCL kernels all the kernels are enqueued on the queue associated with <a class="el" href="classarm__compute_1_1_c_l_scheduler.xhtml" title="Provides global access to a CL context and command queue.">CLScheduler</a> and the queue is then flushed. For the runtime functions, there is an extra method implemented: prepare(), this method prepares the function for the run, it does all the heavy operations that are done only once (reshape the weight, release the memory not necessary after the reshape, etc). The prepare method can be called standalone or in the first run, if not called before, after then the function will be marked as prepared. The files we add are:</p>
<p>OpenCL function</p><ul>
<li><a class="el" href="_c_l_reshape_layer_8h.xhtml">arm_compute/runtime/CL/functions/CLReshapeLayer.h</a></li>
<li><a class="el" href="_c_l_reshape_layer_8cpp.xhtml">src/runtime/CL/functions/CLReshapeLayer.cpp</a></li>
@@ -201,8 +201,8 @@
<li><a class="el" href="_n_e_functions_8h.xhtml">arm_compute/runtime/NEON/NEFunctions.h</a></li>
</ul>
<p>For the special case where the new function calls only one kernel, we could use as base class <a class="el" href="classarm__compute_1_1_i_c_l_simple_function.xhtml" title="Basic interface for functions which have a single OpenCL kernel.">ICLSimpleFunction</a> or <a class="el" href="classarm__compute_1_1_i_n_e_simple_function.xhtml" title="Basic interface for functions which have a single NEON kernel.">INESimpleFunction</a>. The configure and the validate methods will simply call the corresponding functions. The structure will be: </p><div class="fragment"><div class="line"><span class="keyword">using namespace </span><a class="code" href="namespacearm__compute.xhtml">arm_compute</a>;</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> <a class="code" href="classarm__compute_1_1_c_l_reshape_layer.xhtml#a074e10cfb217e657b9e81adeca2abc68">CLReshapeLayer::configure</a>(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *input, <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *output)</div><div class="line">{</div><div class="line"> <span class="keyword">auto</span> k = arm_compute::support::cpp14::make_unique<CLReshapeLayerKernel>();</div><div class="line"> k->configure(input, output);</div><div class="line"> _kernel = std::move(k);</div><div class="line">}</div><div class="line"></div><div class="line"><a class="code" href="classarm__compute_1_1_status.xhtml">Status</a> <a class="code" href="classarm__compute_1_1_c_l_reshape_layer.xhtml#a968b23a6ef327fcfb5b99d58e3fbe883">CLReshapeLayer::validate</a>(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *input, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *output)</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="classarm__compute_1_1_c_l_reshape_layer_kernel.xhtml#a968b23a6ef327fcfb5b99d58e3fbe883">CLReshapeLayerKernel::validate</a>(input, output);</div><div class="line">}</div></div><!-- fragment --><p>If the function is more complicated and calls more than one kernel we have to use the memory manager to manage the intermediate tensors; in the configure() method we call the manage() function passing the tensor to keep track, in the run method we will have to acquire all the buffer managed and released at the end. For OpenCL if we want to add two tensor input and reshape the result:</p>
-<div class="fragment"><div class="line"><span class="keyword">using namespace </span><a class="code" href="namespacearm__compute.xhtml">arm_compute</a>;</div><div class="line"></div><div class="line">CLAddReshapeLayer:: CLAddReshapeLayer(std::shared_ptr<IMemoryManager> memory_manager)</div><div class="line"> : _memory_group(std::move(memory_manager))</div><div class="line">{</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> CLAddReshapeLayer::configure(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *input2, <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *output)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocate memory</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>();</div><div class="line"> add_output.allocator()->init(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Manage intermediate buffers</span></div><div class="line"> memory_group.manage(&_addOutput);</div><div class="line"></div><div class="line"> <span class="comment">// Initialise kernel</span></div><div class="line"> _add_kernel.configure(input1, input2, &add_output);</div><div class="line"> _reshape_kernel.configure(&add_output, output);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate intermediate tensors</span></div><div class="line"> add_output.allocator()->allocate();</div><div class="line">}</div><div class="line"></div><div class="line"><a class="code" href="classarm__compute_1_1_status.xhtml">Status</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ae02c6fc90d9c60c634bfa258049eb46b">CLAddReshapeLayer::validate</a>(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *input2, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *output)</div><div class="line">{</div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> add_output();</div><div class="line"> <a class="code" href="_error_8h.xhtml#a206d6e247e0957ac3dee45d27756fc25">ARM_COMPUTE_RETURN_ERROR_ON</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ae02c6fc90d9c60c634bfa258049eb46b">CLAddLayerKernel::validate</a>(input1, input2, add_output));</div><div class="line"> <a class="code" href="_error_8h.xhtml#a206d6e247e0957ac3dee45d27756fc25">ARM_COMPUTE_RETURN_ERROR_ON</a>(<a class="code" href="classarm__compute_1_1_c_l_reshape_layer_kernel.xhtml#a968b23a6ef327fcfb5b99d58e3fbe883">CLReshapeLayerKernel::validate</a>(add_output, output));</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="classarm__compute_1_1_status.xhtml">Status</a>{};</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> CLAddReshapeLayer::run()</div><div class="line">{</div><div class="line"> memory_group.acquire();</div><div class="line"></div><div class="line"> <span class="comment">// Run Add</span></div><div class="line"> add_kernel.run();</div><div class="line"></div><div class="line"> <span class="comment">// Run Reshape</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_c_l_scheduler.xhtml#a9b58d0eb9a2af8e6d7908695e1557d6c">CLScheduler::get</a>().<a class="code" href="classarm__compute_1_1_c_l_scheduler.xhtml#ae1a643e517f50bf0392fb6516dd7cf67">enqueue</a>(reshape_kernel);</div><div class="line"></div><div class="line"> memory_group.release();</div><div class="line">}</div></div><!-- fragment --><p>For NEON:</p>
-<div class="fragment"><div class="line"><span class="keyword">using namespace </span><a class="code" href="namespacearm__compute.xhtml">arm_compute</a>;</div><div class="line"></div><div class="line">NEAddReshapeLayer:: NEAddReshapeLayer (std::shared_ptr<IMemoryManager> memory_manager)</div><div class="line"> : _memory_group(std::move(memory_manager))</div><div class="line">{</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> NEAddReshapeLayer::configure(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *input2, <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *output)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocate memory</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>();</div><div class="line"> add_output.allocator()->init(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Manage intermediate buffers</span></div><div class="line"> memory_group.manage(&_addOutput);</div><div class="line"></div><div class="line"> <span class="comment">// Initialise kernel</span></div><div class="line"> add_kernel.configure(input1, input2, &addOutput);</div><div class="line"> reshape_kernel.configure(&addOutput, output);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate intermediate tensors</span></div><div class="line"> add_output.allocator()->allocate();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> NEAddReshapeLayer::run()</div><div class="line">{</div><div class="line"> memory_group.acquire();</div><div class="line"></div><div class="line"> <span class="comment">// Run Add</span></div><div class="line"> add_kernel.run();</div><div class="line"></div><div class="line"> <span class="comment">// Run Reshape</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_scheduler.xhtml#a0d63ca713bab377aabcfb63c192b8429">NEScheduler::get</a>().<a class="code" href="classarm__compute_1_1_i_scheduler.xhtml#a4e58f95544bd5ac6559a421671bd9842">schedule</a>(_reshape_kernel.get(), <a class="code" href="classarm__compute_1_1_window.xhtml#ad2d402364fa822b0b7775081291eeca9">Window::DimY</a>);</div><div class="line"></div><div class="line"> memory_group.release();</div><div class="line">}</div></div><!-- fragment --><p>At this point, everything is in place at the library level. If you are following an tests driven implementation and all the tests are already in place, we can call the function configuration in the fixture and remove any redundant code like the allocation of the intermediate tensors since it's done in the function. Run the final tests to check the results match with the expected results from the reference implementation.</p>
+<div class="fragment"><div class="line"><span class="keyword">using namespace </span><a class="code" href="namespacearm__compute.xhtml">arm_compute</a>;</div><div class="line"></div><div class="line">CLAddReshapeLayer:: CLAddReshapeLayer(std::shared_ptr<IMemoryManager> memory_manager)</div><div class="line"> : _memory_group(std::move(memory_manager))</div><div class="line">{</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> CLAddReshapeLayer::configure(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *input2, <a class="code" href="classarm__compute_1_1_i_c_l_tensor.xhtml">ICLTensor</a> *output)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocate memory</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>();</div><div class="line"> add_output.allocator()->init(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Manage intermediate buffers</span></div><div class="line"> memory_group.manage(&_addOutput);</div><div class="line"></div><div class="line"> <span class="comment">// Initialise kernel</span></div><div class="line"> _add_kernel.configure(input1, input2, &add_output);</div><div class="line"> _reshape_kernel.configure(&add_output, output);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate intermediate tensors</span></div><div class="line"> add_output.allocator()->allocate();</div><div class="line">}</div><div class="line"></div><div class="line"><a class="code" href="classarm__compute_1_1_status.xhtml">Status</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ae02c6fc90d9c60c634bfa258049eb46b">CLAddReshapeLayer::validate</a>(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *input2, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor_info.xhtml">ITensorInfo</a> *output)</div><div class="line">{</div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> add_output();</div><div class="line"> <a class="code" href="_error_8h.xhtml#a206d6e247e0957ac3dee45d27756fc25">ARM_COMPUTE_RETURN_ERROR_ON</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ae02c6fc90d9c60c634bfa258049eb46b">CLAddLayerKernel::validate</a>(input1, input2, add_output));</div><div class="line"> <a class="code" href="_error_8h.xhtml#a206d6e247e0957ac3dee45d27756fc25">ARM_COMPUTE_RETURN_ERROR_ON</a>(<a class="code" href="classarm__compute_1_1_c_l_reshape_layer_kernel.xhtml#a968b23a6ef327fcfb5b99d58e3fbe883">CLReshapeLayerKernel::validate</a>(add_output, output));</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="classarm__compute_1_1_status.xhtml">Status</a>{};</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#aae8f98973dd49e5afd7309bb34d4e3c3">CLAddReshapeLayer::run</a>()</div><div class="line">{</div><div class="line"> memory_group.acquire();</div><div class="line"></div><div class="line"> <span class="comment">// Run Add</span></div><div class="line"> add_kernel.run();</div><div class="line"></div><div class="line"> <span class="comment">// Run Reshape</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_c_l_scheduler.xhtml#a9b58d0eb9a2af8e6d7908695e1557d6c">CLScheduler::get</a>().<a class="code" href="classarm__compute_1_1_c_l_scheduler.xhtml#ae1a643e517f50bf0392fb6516dd7cf67">enqueue</a>(reshape_kernel);</div><div class="line"></div><div class="line"> memory_group.release();</div><div class="line">}</div></div><!-- fragment --><p>For NEON:</p>
+<div class="fragment"><div class="line"><span class="keyword">using namespace </span><a class="code" href="namespacearm__compute.xhtml">arm_compute</a>;</div><div class="line"></div><div class="line">NEAddReshapeLayer:: NEAddReshapeLayer (std::shared_ptr<IMemoryManager> memory_manager)</div><div class="line"> : _memory_group(std::move(memory_manager))</div><div class="line">{</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> NEAddReshapeLayer::configure(<span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *input1, <span class="keyword">const</span> <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *input2, <a class="code" href="classarm__compute_1_1_i_tensor.xhtml">ITensor</a> *output)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocate memory</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_tensor_info.xhtml">TensorInfo</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>();</div><div class="line"> add_output.allocator()->init(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a4f4125dba5283887b34f889b1c615c0c">info</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Manage intermediate buffers</span></div><div class="line"> memory_group.manage(&_addOutput);</div><div class="line"></div><div class="line"> <span class="comment">// Initialise kernel</span></div><div class="line"> add_kernel.configure(input1, input2, &addOutput);</div><div class="line"> reshape_kernel.configure(&addOutput, output);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate intermediate tensors</span></div><div class="line"> add_output.allocator()->allocate();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#aae8f98973dd49e5afd7309bb34d4e3c3">NEAddReshapeLayer::run</a>()</div><div class="line">{</div><div class="line"> memory_group.acquire();</div><div class="line"></div><div class="line"> <span class="comment">// Run Add</span></div><div class="line"> add_kernel.run();</div><div class="line"></div><div class="line"> <span class="comment">// Run Reshape</span></div><div class="line"> <a class="code" href="classarm__compute_1_1_scheduler.xhtml#a0d63ca713bab377aabcfb63c192b8429">NEScheduler::get</a>().<a class="code" href="classarm__compute_1_1_i_scheduler.xhtml#a4e58f95544bd5ac6559a421671bd9842">schedule</a>(_reshape_kernel.get(), <a class="code" href="classarm__compute_1_1_window.xhtml#ad2d402364fa822b0b7775081291eeca9">Window::DimY</a>);</div><div class="line"></div><div class="line"> memory_group.release();</div><div class="line">}</div></div><!-- fragment --><p>At this point, everything is in place at the library level. If you are following an tests driven implementation and all the tests are already in place, we can call the function configuration in the fixture and remove any redundant code like the allocation of the intermediate tensors since it's done in the function. Run the final tests to check the results match with the expected results from the reference implementation.</p>
<h2><a class="anchor" id="S4_1_4_add_validation"></a>
Add validation artifacts</h2>
<h3><a class="anchor" id="S4_1_4_1_add_reference"></a>
@@ -232,7 +232,7 @@
Add a fixture and a data test case</h3>
<p>Benchmark and validation tests are based on the same framework to setup and run the tests. In addition to running simple, self-contained test functions the framework supports fixtures and data test cases. Fixtures can be used to share common setup, teardown or even run tasks among multiple test cases, for that purpose a fixture can define a "setup", "teardown" and "run" method. Adding tests for the new operator in the runtime library we need to implement at least the setup method, that is used to call two methods for configure, run and return the output respectively of the target (CL or Neon) and the reference (C++ implementation).</p>
<p>For example let's have a look at Reshape Layer Fixture :</p>
-<div class="fragment"><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> TensorType, <span class="keyword">typename</span> AccessorType, <span class="keyword">typename</span> FunctionType, <span class="keyword">typename</span> T></div><div class="line"><span class="keyword">class </span>ReshapeLayerValidationFixture : <span class="keyword">public</span> framework::Fixture</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span>...></div><div class="line"> <span class="keywordtype">void</span> setup(TensorShape <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, TensorShape <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>)</div><div class="line"> {</div><div class="line"> _target = compute_target(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>);</div><div class="line"> _reference = compute_reference(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>);</div><div class="line"> }</div><div class="line"></div><div class="line"><span class="keyword">protected</span>:</div><div class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span> U></div><div class="line"> <span class="keywordtype">void</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(<a class="code" href="namespacearm__compute.xhtml#a1ce9b523fd4f3b5bbcadcd796183455aa4c614360da93c0a041b22e537de151eb">U</a> &&tensor, <span class="keywordtype">int</span> i)</div><div class="line"> {</div><div class="line"> <a class="code" href="namespacearm__compute_1_1test.xhtml#a71326f0909d77386e29b511e1990a11f">library</a>->fill_tensor_uniform(tensor, i);</div><div class="line"> }</div><div class="line"></div><div class="line"> TensorType compute_target(<span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>)</div><div class="line"> {</div><div class="line"> <span class="comment">// Check if indeed the input shape can be reshape to the output one</span></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>.total_size() == <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>.total_size(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Create tensors</span></div><div class="line"> TensorType <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a> = create_tensor<TensorType>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>);</div><div class="line"> TensorType <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a> = create_tensor<TensorType>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Create and configure function</span></div><div class="line"> FunctionType reshape;</div><div class="line"></div><div class="line"> reshape.configure(&<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>);</div><div class="line"></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.info()->is_resizable(), framework::LogLevel::ERRORS);</div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#ad45f0c01a0713dfb6bd7232c7f396fc4">info</a>()-><a class="code" href="classarm__compute_1_1_tensor_info.xhtml#aaee6555ace43b03173844b1a228a3fc3">is_resizable</a>(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate tensors</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.allocator()->allocate();</div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#a4083de30daebd6bdee6b35d9c8262108">allocator</a>()-><a class="code" href="classarm__compute_1_1_c_l_tensor_allocator.xhtml#a6e509c2a177b0b29e9e2369535094dee">allocate</a>();</div><div class="line"></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(!<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.info()->is_resizable(), framework::LogLevel::ERRORS);</div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(!<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#ad45f0c01a0713dfb6bd7232c7f396fc4">info</a>()-><a class="code" href="classarm__compute_1_1_tensor_info.xhtml#aaee6555ace43b03173844b1a228a3fc3">is_resizable</a>(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Fill tensors</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(AccessorType(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>), 0);</div><div class="line"></div><div class="line"> <span class="comment">// Compute function</span></div><div class="line"> reshape.run();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>;</div><div class="line"> }</div><div class="line"></div><div class="line"> SimpleTensor<T> compute_reference(<span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a>)</div><div class="line"> {</div><div class="line"> <span class="comment">// Create reference</span></div><div class="line"> SimpleTensor<T> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>{ <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ac2ad7f431e3446fddcd9b6b9f93c4c14">data_type</a> };</div><div class="line"></div><div class="line"> <span class="comment">// Fill reference</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, 0);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> reference::reshape_layer<T>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>);</div><div class="line"> }</div><div class="line"></div><div class="line"> TensorType _target{};</div><div class="line"> SimpleTensor<T> _reference{};</div><div class="line">};</div></div><!-- fragment --><p> In the fixture class above we can see that the setup method computes the target and reference and store them in the two members _target and _reference which will be used later to check for correctness. The compute_target method reflects the exact behavior expected when we call a function. The input and output tensor must be declared, function configured, tensors allocated, the input tensor filled with required data, and finally, the function must be run and the results returned. This fixture is used in the test case, that is a parameterized test case that inherits from a fixture. The test case will have access to all public and protected members of the fixture. Only the setup and teardown methods of the fixture will be used. The setup method of the fixture needs to be a template and must accept inputs from the dataset as arguments. The body of this function will be used as a test function. For the fixture test case the first argument is the name of the test case (has to be unique within the enclosing test suite), the second argument is the class name of the fixture, the third argument is the dataset mode in which the test will be active (PRECOMMIT or NIGTHLY) and the fourth argument is the dataset. For example:</p>
+<div class="fragment"><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> TensorType, <span class="keyword">typename</span> AccessorType, <span class="keyword">typename</span> FunctionType, <span class="keyword">typename</span> T></div><div class="line"><span class="keyword">class </span>ReshapeLayerValidationFixture : <span class="keyword">public</span> framework::Fixture</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span>...></div><div class="line"> <span class="keywordtype">void</span> setup(TensorShape <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, TensorShape <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>)</div><div class="line"> {</div><div class="line"> _target = compute_target(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>);</div><div class="line"> _reference = compute_reference(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>);</div><div class="line"> }</div><div class="line"></div><div class="line"><span class="keyword">protected</span>:</div><div class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span> U></div><div class="line"> <span class="keywordtype">void</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(<a class="code" href="namespacearm__compute.xhtml#a1ce9b523fd4f3b5bbcadcd796183455aa4c614360da93c0a041b22e537de151eb">U</a> &&tensor, <span class="keywordtype">int</span> i)</div><div class="line"> {</div><div class="line"> <a class="code" href="namespacearm__compute_1_1test.xhtml#a71326f0909d77386e29b511e1990a11f">library</a>->fill_tensor_uniform(tensor, i);</div><div class="line"> }</div><div class="line"></div><div class="line"> TensorType compute_target(<span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>)</div><div class="line"> {</div><div class="line"> <span class="comment">// Check if indeed the input shape can be reshape to the output one</span></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>.total_size() == <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>.total_size(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Create tensors</span></div><div class="line"> TensorType <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a> = create_tensor<TensorType>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>);</div><div class="line"> TensorType <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a> = create_tensor<TensorType>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>);</div><div class="line"></div><div class="line"> <span class="comment">// Create and configure function</span></div><div class="line"> FunctionType reshape;</div><div class="line"></div><div class="line"> reshape.configure(&<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>);</div><div class="line"></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.info()->is_resizable(), framework::LogLevel::ERRORS);</div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#ad45f0c01a0713dfb6bd7232c7f396fc4">info</a>()-><a class="code" href="classarm__compute_1_1_tensor_info.xhtml#aaee6555ace43b03173844b1a228a3fc3">is_resizable</a>(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Allocate tensors</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.allocator()->allocate();</div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#a4083de30daebd6bdee6b35d9c8262108">allocator</a>()-><a class="code" href="classarm__compute_1_1_c_l_tensor_allocator.xhtml#a6e509c2a177b0b29e9e2369535094dee">allocate</a>();</div><div class="line"></div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(!<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>.info()->is_resizable(), framework::LogLevel::ERRORS);</div><div class="line"> <a class="code" href="_asserts_8h.xhtml#adc60af942e951dc93e22b97b41809b51">ARM_COMPUTE_EXPECT</a>(!<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>.<a class="code" href="classarm__compute_1_1_c_l_tensor.xhtml#ad45f0c01a0713dfb6bd7232c7f396fc4">info</a>()-><a class="code" href="classarm__compute_1_1_tensor_info.xhtml#aaee6555ace43b03173844b1a228a3fc3">is_resizable</a>(), framework::LogLevel::ERRORS);</div><div class="line"></div><div class="line"> <span class="comment">// Fill tensors</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(AccessorType(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>), 0);</div><div class="line"></div><div class="line"> <span class="comment">// Compute function</span></div><div class="line"> reshape.run();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#adbf67dcee294e673cf796f1ed8aeb6a4">dst</a>;</div><div class="line"> }</div><div class="line"></div><div class="line"> SimpleTensor<T> compute_reference(<span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <span class="keyword">const</span> TensorShape &<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>, <a class="code" href="namespacearm__compute.xhtml#ad8ed01ff3ff33333d8e19db4d2818bb6">DataType</a> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a>)</div><div class="line"> {</div><div class="line"> <span class="comment">// Create reference</span></div><div class="line"> SimpleTensor<T> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>{ <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a865514e30baa11b11c8fa65f944532fb">input_shape</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a5f5b6c4337eac9e2e0046ca2304d80dc">data_type</a> };</div><div class="line"></div><div class="line"> <span class="comment">// Fill reference</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a1643f4cb252152ed8ffc0df84744ad5d">fill</a>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, 0);</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> reference::reshape_layer<T>(<a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a989ab3e96426615bb98e04e0235088ca">src</a>, <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#a7fc93f37dac131a1a40b7921f9df3a9a">output_shape</a>);</div><div class="line"> }</div><div class="line"></div><div class="line"> TensorType _target{};</div><div class="line"> SimpleTensor<T> _reference{};</div><div class="line">};</div></div><!-- fragment --><p> In the fixture class above we can see that the setup method computes the target and reference and store them in the two members _target and _reference which will be used later to check for correctness. The compute_target method reflects the exact behavior expected when we call a function. The input and output tensor must be declared, function configured, tensors allocated, the input tensor filled with required data, and finally, the function must be run and the results returned. This fixture is used in the test case, that is a parameterized test case that inherits from a fixture. The test case will have access to all public and protected members of the fixture. Only the setup and teardown methods of the fixture will be used. The setup method of the fixture needs to be a template and must accept inputs from the dataset as arguments. The body of this function will be used as a test function. For the fixture test case the first argument is the name of the test case (has to be unique within the enclosing test suite), the second argument is the class name of the fixture, the third argument is the dataset mode in which the test will be active (PRECOMMIT or NIGTHLY) and the fourth argument is the dataset. For example:</p>
<div class="fragment"><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">using</span> <a class="code" href="namespacearm__compute_1_1test_1_1benchmark.xhtml#a74a10374253178ae54e1baab173698a1">CLActivationLayerFixture</a> = ActivationValidationFixture<CLTensor, CLAccessor, CLActivationLayer, T>;</div></div><!-- fragment --> <div class="fragment"><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#acd09bed517e43d28823e69494f259835">TEST_SUITE</a>(CL)</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#acd09bed517e43d28823e69494f259835">TEST_SUITE</a>(ActivationLayer)</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#acd09bed517e43d28823e69494f259835">TEST_SUITE</a>(Float)</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#acd09bed517e43d28823e69494f259835">TEST_SUITE</a>(FP16)</div></div><!-- fragment --> <div class="fragment"><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#a42699a26fbdddf91da4aa58a610bb8a8">FIXTURE_DATA_TEST_CASE</a>(RunSmall, CLActivationLayerFixture<half>, framework::DatasetMode::PRECOMMIT, <a class="code" href="namespacearm__compute_1_1test_1_1benchmark.xhtml#ac637b6be52ec2d9a3671f493f8b71042">combine</a>(<a class="code" href="namespacearm__compute_1_1test_1_1benchmark.xhtml#ac637b6be52ec2d9a3671f493f8b71042">combine</a>(datasets::SmallShapes(), ActivationDataset),</div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1framework_1_1dataset.xhtml#a352791fb808d42a82ad70df5efa3508b">framework::dataset::make</a>(<span class="stringliteral">"DataType"</span>,</div><div class="line"> <a class="code" href="namespacearm__compute.xhtml#ab4e88c89b3b7ea1735996cc4def22d58a56d8353718e6fdc78b8d69078a2cdb94">DataType::F16</a>)))</div><div class="line">{</div><div class="line"> <span class="comment">// Validate output</span></div><div class="line"> <a class="code" href="namespacearm__compute_1_1test_1_1validation.xhtml#ae02c6fc90d9c60c634bfa258049eb46b">validate</a>(CLAccessor(_target), _reference, tolerance(_function, _data_type));</div><div class="line">}</div></div><!-- fragment --><div class="fragment"><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#a603cb7f45efd81606e51686da9aeebd9">TEST_SUITE_END</a>()</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#a603cb7f45efd81606e51686da9aeebd9">TEST_SUITE_END</a>()</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#a603cb7f45efd81606e51686da9aeebd9">TEST_SUITE_END</a>()</div><div class="line"><a class="code" href="tests_2framework_2_macros_8h.xhtml#a603cb7f45efd81606e51686da9aeebd9">TEST_SUITE_END</a>()</div></div><!-- fragment --><p>This will produce a set of tests that can be filtered with "CL/ReshapeLayer/Float/FP16/RunSmall". Each test produced from the cartesian product of the dataset is associated to a number and can be filtered specifying all the parameters. </p>
</div></div><!-- PageDoc -->
</div><!-- contents -->
@@ -240,7 +240,7 @@
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
- <li class="footer">Generated on Thu May 23 2019 17:11:27 for Compute Library by
+ <li class="footer">Generated on Mon Sep 2 2019 11:47:30 for Compute Library by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.15 </li>
</ul>