• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_TEST_CONVOLUTION_FIXTURE
25 #define ARM_COMPUTE_TEST_CONVOLUTION_FIXTURE
26 
27 #include "arm_compute/core/TensorShape.h"
28 #include "arm_compute/core/Types.h"
29 #include "tests/AssetsLibrary.h"
30 #include "tests/Globals.h"
31 #include "tests/IAccessor.h"
32 #include "tests/framework/Asserts.h"
33 #include "tests/framework/Fixture.h"
34 #include "tests/validation/reference/Convolution.h"
35 
36 #include <random>
37 
38 namespace arm_compute
39 {
40 namespace test
41 {
42 namespace validation
43 {
44 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
45 class ConvolutionValidationFixture : public framework::Fixture
46 {
47 protected:
48     template <typename...>
49     void setup(TensorShape shape, DataType output_data_type, BorderMode border_mode, const unsigned int width, const unsigned int height, const bool is_separable = false)
50     {
51         std::mt19937                           gen(library->seed());
52         std::uniform_int_distribution<uint8_t> distribution(0, 255);
53         std::uniform_int_distribution<uint8_t> scale_distribution(1, 255);
54         const uint8_t                          constant_border_value = distribution(gen);
55 
56         // Generate random scale value between 1 and 255.
57         const uint32_t scale = scale_distribution(gen);
58 
59         ARM_COMPUTE_ERROR_ON(3 != width && 5 != width && 7 != width && 9 != width);
60         ARM_COMPUTE_ERROR_ON(3 != height && 5 != height && 7 != height && 9 != height);
61 
62         std::vector<int16_t> conv(width * height);
63 
64         _width  = width;
65         _height = height;
66 
67         if(is_separable)
68         {
69             init_separable_conv(conv.data(), width, height, library->seed());
70         }
71         else
72         {
73             init_conv(conv.data(), width, height, library->seed());
74         }
75 
76         _target    = compute_target(shape, output_data_type, conv.data(), scale, border_mode, constant_border_value);
77         _reference = compute_reference(shape, output_data_type, conv.data(), scale, border_mode, constant_border_value);
78     }
79 
80     template <typename U>
fill(U && tensor,int i)81     void fill(U &&tensor, int i)
82     {
83         library->fill_tensor_uniform(tensor, i);
84     }
85 
compute_reference(const TensorShape & shape,DataType output_data_type,const int16_t * conv,uint32_t scale,BorderMode border_mode,uint8_t constant_border_value)86     SimpleTensor<T> compute_reference(const TensorShape &shape, DataType output_data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
87     {
88         // Create reference
89         SimpleTensor<uint8_t> src{ shape, DataType::U8 };
90 
91         // Fill reference
92         fill(src, 0);
93 
94         // Compute reference
95         return reference::convolution<T>(src, output_data_type, conv, scale, border_mode, constant_border_value, _width, _height);
96     }
97 
98     virtual TensorType compute_target(const TensorShape &shape, DataType output_data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value) = 0;
99 
100     BorderMode      _border_mode{};
101     TensorType      _target{};
102     SimpleTensor<T> _reference{};
103     unsigned int    _width{};
104     unsigned int    _height{};
105 };
106 
107 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
108 class ConvolutionSquareValidationFixture : public ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>
109 {
110 public:
111     template <typename...>
setup(TensorShape shape,DataType output_data_type,BorderMode border_mode,const unsigned int width)112     void setup(TensorShape shape, DataType output_data_type, BorderMode border_mode, const unsigned int width)
113     {
114         ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, output_data_type, border_mode, width, width);
115     }
116 
117 protected:
compute_target(const TensorShape & shape,DataType output_data_type,const int16_t * conv,uint32_t scale,BorderMode border_mode,uint8_t constant_border_value)118     TensorType compute_target(const TensorShape &shape, DataType output_data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
119     {
120         // Create tensors
121         TensorType src = create_tensor<TensorType>(shape, DataType::U8);
122         TensorType dst = create_tensor<TensorType>(shape, output_data_type);
123 
124         // Create and configure function
125         FunctionType convolution;
126         convolution.configure(&src, &dst, conv, scale, border_mode, constant_border_value);
127 
128         ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
129         ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
130 
131         // Allocate tensors
132         src.allocator()->allocate();
133         dst.allocator()->allocate();
134 
135         ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
136         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
137 
138         // Fill tensors
139         this->fill(AccessorType(src), 0);
140         this->fill(AccessorType(dst), 1);
141 
142         // Compute function
143         convolution.run();
144 
145         return dst;
146     }
147 };
148 
149 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
150 class ConvolutionSeparableValidationFixture : public ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>
151 {
152 public:
153     template <typename...>
setup(TensorShape shape,DataType output_data_type,BorderMode border_mode,const unsigned int width)154     void setup(TensorShape shape, DataType output_data_type, BorderMode border_mode, const unsigned int width)
155     {
156         ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, output_data_type, border_mode, width, width, true);
157     }
158 
159 protected:
compute_target(const TensorShape & shape,DataType output_data_type,const int16_t * conv,uint32_t scale,BorderMode border_mode,uint8_t constant_border_value)160     TensorType compute_target(const TensorShape &shape, DataType output_data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
161     {
162         // Create tensors
163         TensorType src = create_tensor<TensorType>(shape, DataType::U8);
164         TensorType dst = create_tensor<TensorType>(shape, output_data_type);
165 
166         // Create and configure function
167         FunctionType convolution;
168         convolution.configure(&src, &dst, conv, scale, border_mode, constant_border_value);
169 
170         ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
171         ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
172 
173         // Allocate tensors
174         src.allocator()->allocate();
175         dst.allocator()->allocate();
176 
177         ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
178         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
179 
180         // Fill tensors
181         this->fill(AccessorType(src), 0);
182         this->fill(AccessorType(dst), 1);
183 
184         // Compute function
185         convolution.run();
186 
187         return dst;
188     }
189 };
190 
191 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
192 class ConvolutionRectangleValidationFixture : public ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>
193 {
194 public:
195     template <typename...>
setup(TensorShape shape,DataType output_data_type,BorderMode border_mode,const unsigned int width,const unsigned int height)196     void setup(TensorShape shape, DataType output_data_type, BorderMode border_mode, const unsigned int width, const unsigned int height)
197     {
198         ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, output_data_type, border_mode, width, height);
199     }
200 
201 protected:
compute_target(const TensorShape & shape,DataType output_data_type,const int16_t * conv,uint32_t scale,BorderMode border_mode,uint8_t constant_border_value)202     TensorType compute_target(const TensorShape &shape, DataType output_data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
203     {
204         // Create tensors
205         TensorType src = create_tensor<TensorType>(shape, DataType::U8);
206         TensorType dst = create_tensor<TensorType>(shape, output_data_type);
207 
208         // Create and configure function
209         FunctionType convolution;
210         convolution.configure(&src, &dst, conv, this->_width, this->_height, scale, border_mode, constant_border_value);
211 
212         ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
213         ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
214 
215         // Allocate tensors
216         src.allocator()->allocate();
217         dst.allocator()->allocate();
218 
219         ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
220         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
221 
222         // Fill tensors
223         this->fill(AccessorType(src), 0);
224         this->fill(AccessorType(dst), 1);
225 
226         // Compute function
227         convolution.run();
228 
229         return dst;
230     }
231 };
232 } // namespace validation
233 } // namespace test
234 } // namespace arm_compute
235 #endif /* ARM_COMPUTE_TEST_CONVOLUTION_FIXTURE */
236