Compute Library
 20.02.1
StackLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 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  */
25 #include "arm_compute/core/Types.h"
30 #include "tests/NEON/Accessor.h"
32 #include "tests/datasets/ShapeDatasets.h"
34 #include "tests/framework/Macros.h"
37 #include "tests/validation/fixtures/StackLayerFixture.h"
38 
39 #include <vector>
40 
41 namespace arm_compute
42 {
43 namespace test
44 {
45 namespace validation
46 {
47 namespace
48 {
49 // *INDENT-OFF*
50 // clang-format off
51 /** Data types */
52 const auto data_types = framework::dataset::make("DataType", { DataType::QASYMM8, DataType::F16, DataType::F32 });
53 
54 /** Num tensors values to test */
55 const auto n_values = framework::dataset::make("NumTensors", { 3, 4 });
56 
57 /** Shapes 1D to test */
58 const auto shapes_1d_small = combine(datasets::Small1DShapes(), framework::dataset::make("Axis", -1, 2));
59 
60 /** Shapes 2D to test */
61 const auto shapes_2d_small = combine(datasets::Small2DShapes(), framework::dataset::make("Axis", -2, 3));
62 
63 /** Shapes 3D to test */
64 const auto shapes_3d_small = combine(datasets::Small3DShapes(), framework::dataset::make("Axis", -3, 4));
65 
66 /** Shapes 4D to test */
67 const auto shapes_4d_small = combine(datasets::Small4DShapes(), framework::dataset::make("Axis", -4, 5));
68 
69 /** Shapes 1D to test */
70 const auto shapes_1d_large = combine(datasets::Large1DShapes(), framework::dataset::make("Axis", -1, 2));
71 
72 /** Shapes 2D to test */
73 const auto shapes_2d_large = combine(datasets::Medium2DShapes(), framework::dataset::make("Axis", -2, 3));
74 
75 /** Shapes 3D to test */
76 const auto shapes_3d_large = combine(datasets::Medium3DShapes(), framework::dataset::make("Axis", -3, 4));
77 
78 /** Shapes 4D to test */
79 const auto shapes_4d_large = combine(datasets::Medium4DShapes(), framework::dataset::make("Axis", -4, 5));
80 
81 /** Configuration test */
83 {
84  // Wrap around negative values
85  const unsigned int axis_u = wrap_around(axis, static_cast<int>(shape_in.num_dimensions() + 1));
86 
87  const TensorShape shape_dst = compute_stack_shape(TensorInfo(shape_in, 1, data_type), axis_u, num_tensors);
88 
89  std::vector<Tensor> tensors(num_tensors);
90  std::vector<ITensor*> src(num_tensors);
91 
92  // Create vector of input tensors
93  for(int i = 0; i < num_tensors; ++i)
94  {
95  tensors[i] = create_tensor<Tensor>(shape_in, data_type);
96  src[i] = &(tensors[i]);
98  }
99 
100  // Create tensors
101  Tensor dst = create_tensor<Tensor>(shape_dst, data_type);
102 
104 
105  // Create and configure function
106  NEStackLayer stack;
107  stack.configure(src, axis, &dst);
108 }
109 } // namespace
110 
111 /** Fixture to use */
112 template<typename T>
113 using NEStackLayerFixture = StackLayerValidationFixture<Tensor, ITensor, Accessor, NEStackLayer, T>;
114 
116 
117 TEST_SUITE(NEON)
118 TEST_SUITE(StackLayer)
119 
120 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(
121  framework::dataset::make("InputInfo",
122 {
123  std::vector<TensorInfo>{ TensorInfo(TensorShape(9U, 8U), 1, DataType::U8) },
124  std::vector<TensorInfo>{ TensorInfo(TensorShape(1U, 2U), 1, DataType::U8) , TensorInfo(TensorShape(1U, 2U), 1, DataType::U8), TensorInfo(TensorShape(1U, 2U), 1, DataType::U8)},
125  std::vector<TensorInfo>{ TensorInfo(TensorShape(2U, 3U), 1, DataType::S32) },
126  std::vector<TensorInfo>{ TensorInfo(TensorShape(7U, 5U, 3U, 8U, 2U), 1, DataType::S32), TensorInfo(TensorShape(7U, 5U, 3U, 8U, 2U), 1, DataType::S32)},
127  std::vector<TensorInfo>{ TensorInfo(TensorShape(9U, 8U), 1, DataType::S32) },
128 }),
129 framework::dataset::make("OutputInfo",
130 {
131  TensorInfo(TensorShape(1U, 9U, 8U), 1, DataType::U8), // Passes, stack 1 tensor on x axis
132  TensorInfo(TensorShape(1U, 3U, 2U), 1, DataType::U8), // Passes, stack 3 tensors on y axis
133  TensorInfo(TensorShape(1U, 2U, 3U), 1, DataType::S32), // fails axis < (- input's rank)
134  TensorInfo(TensorShape(3U, 7U, 5U), 1, DataType::S32), // fails, input dimensions > 4
135  TensorInfo(TensorShape(1U, 2U, 3U), 1, DataType::U8), // fails mismatching data types
136 })),
137 framework::dataset::make("Axis", { -3, 1, -4, -3, 1 })),
138 framework::dataset::make("Expected", { true, true, false, false, false })),
140 {
141  std::vector<TensorInfo> ti(input_info);
142  std::vector<ITensorInfo *> vec(input_info.size());
143  for(size_t j = 0; j < vec.size(); ++j)
144  {
145  vec[j] = &ti[j];
146  }
148 }
149 
150 TEST_SUITE(Shapes1D)
151 
152 DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(shapes_1d_small,
153  data_types),
154  n_values),
156 {
158 }
159 
160 TEST_SUITE(S32)
162  combine(combine(shapes_1d_small,
163  framework::dataset::make("DataType", { DataType::S32 })),
164  n_values))
165 {
166  // Validate output
167  validate(Accessor(_target), _reference);
168 }
169 
171  combine(combine(shapes_1d_large,
172  framework::dataset::make("DataType", { DataType::S32 })),
173  n_values))
174 {
175  // Validate output
176  validate(Accessor(_target), _reference);
177 }
178 TEST_SUITE_END() // S32
179 
180 TEST_SUITE(S16)
181 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<short>, framework::DatasetMode::ALL,
182  combine(combine(shapes_1d_small,
183  framework::dataset::make("DataType", { DataType::S16 })),
184  n_values))
185 {
186  // Validate output
187  validate(Accessor(_target), _reference);
188 }
189 
191  combine(combine(shapes_1d_large,
192  framework::dataset::make("DataType", { DataType::S16 })),
193  n_values))
194 {
195  // Validate output
196  validate(Accessor(_target), _reference);
197 }
198 TEST_SUITE_END() // S16
199 
200 TEST_SUITE(S8)
201 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<char>, framework::DatasetMode::ALL,
202  combine(combine(shapes_1d_small,
203  framework::dataset::make("DataType", { DataType::S8 })),
204  n_values))
205 {
206  // Validate output
207  validate(Accessor(_target), _reference);
208 }
209 
211  combine(combine(shapes_1d_large,
212  framework::dataset::make("DataType", { DataType::S8 })),
213  n_values))
214 {
215  // Validate output
216  validate(Accessor(_target), _reference);
217 }
218 TEST_SUITE_END() // S8
219 TEST_SUITE_END() // Shapes1D
220 
221 TEST_SUITE(Shapes2D)
222 
223 DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(shapes_2d_small,
224  data_types),
225  n_values),
227 {
229 }
230 
231 TEST_SUITE(S32)
233  combine(combine(shapes_2d_small,
234  framework::dataset::make("DataType", { DataType::S32 })),
235  n_values))
236 {
237  // Validate output
238  validate(Accessor(_target), _reference);
239 }
240 
242  combine(combine(shapes_2d_large,
243  framework::dataset::make("DataType", { DataType::S32 })),
244  n_values))
245 {
246  // Validate output
247  validate(Accessor(_target), _reference);
248 }
249 TEST_SUITE_END() // S32
250 
251 TEST_SUITE(S16)
252 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<short>, framework::DatasetMode::ALL,
253  combine(combine(shapes_2d_small,
254  framework::dataset::make("DataType", { DataType::S16 })),
255  n_values))
256 {
257  // Validate output
258  validate(Accessor(_target), _reference);
259 }
260 
262  combine(combine(shapes_2d_large,
263  framework::dataset::make("DataType", { DataType::S16 })),
264  n_values))
265 {
266  // Validate output
267  validate(Accessor(_target), _reference);
268 }
269 TEST_SUITE_END() // S16
270 
271 TEST_SUITE(S8)
272 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<char>, framework::DatasetMode::ALL,
273  combine(combine(shapes_2d_small,
274  framework::dataset::make("DataType", { DataType::S8 })),
275  n_values))
276 {
277  // Validate output
278  validate(Accessor(_target), _reference);
279 }
280 
282  combine(combine(shapes_2d_large,
283  framework::dataset::make("DataType", { DataType::S8 })),
284  n_values))
285 {
286  // Validate output
287  validate(Accessor(_target), _reference);
288 }
289 TEST_SUITE_END() // S8
290 TEST_SUITE_END() // Shapes2D
291 
292 TEST_SUITE(Shapes3D)
293 DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(shapes_3d_small,
294  data_types),
295  n_values),
297 {
299 }
300 
301 TEST_SUITE(S32)
303  combine(combine(shapes_3d_small,
304  framework::dataset::make("DataType", { DataType::S32 })),
305  n_values))
306 {
307  // Validate output
308  validate(Accessor(_target), _reference);
309 }
310 
312  combine(combine(shapes_3d_large,
313  framework::dataset::make("DataType", { DataType::S32 })),
314  n_values))
315 {
316  // Validate output
317  validate(Accessor(_target), _reference);
318 }
319 TEST_SUITE_END() // S32
320 
321 TEST_SUITE(S16)
322 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<short>, framework::DatasetMode::ALL,
323  combine(combine(shapes_3d_small,
324  framework::dataset::make("DataType", { DataType::S16 })),
325  n_values))
326 {
327  // Validate output
328  validate(Accessor(_target), _reference);
329 }
330 
332  combine(combine(shapes_3d_large,
333  framework::dataset::make("DataType", { DataType::S16 })),
334  n_values))
335 {
336  // Validate output
337  validate(Accessor(_target), _reference);
338 }
339 TEST_SUITE_END() // S16
340 
341 TEST_SUITE(S8)
342 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<char>, framework::DatasetMode::ALL,
343  combine(combine(shapes_3d_small,
344  framework::dataset::make("DataType", { DataType::S8 })),
345  n_values))
346 {
347  // Validate output
348  validate(Accessor(_target), _reference);
349 }
350 
352  combine(combine(shapes_3d_large,
353  framework::dataset::make("DataType", { DataType::S8 })),
354  n_values))
355 {
356  // Validate output
357  validate(Accessor(_target), _reference);
358 }
359 TEST_SUITE_END() // S8
360 TEST_SUITE_END() // Shapes3D
361 
362 TEST_SUITE(Shapes4D)
363 DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(shapes_4d_small,
364  data_types),
365  n_values),
367 {
369 }
370 
371 TEST_SUITE(S32)
373  combine(combine(shapes_4d_small,
374  framework::dataset::make("DataType", { DataType::S32 })),
375  n_values))
376 {
377  // Validate output
378  validate(Accessor(_target), _reference);
379 }
380 
382  combine(combine(shapes_4d_large,
383  framework::dataset::make("DataType", { DataType::S32 })),
384  n_values))
385 {
386  // Validate output
387  validate(Accessor(_target), _reference);
388 }
389 TEST_SUITE_END() // S32
390 
391 TEST_SUITE(S16)
392 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<short>, framework::DatasetMode::ALL,
393  combine(combine(shapes_4d_small,
394  framework::dataset::make("DataType", { DataType::S16 })),
395  n_values))
396 {
397  // Validate output
398  validate(Accessor(_target), _reference);
399 }
400 
402  combine(combine(shapes_4d_large,
403  framework::dataset::make("DataType", { DataType::S16 })),
404  n_values))
405 {
406  // Validate output
407  validate(Accessor(_target), _reference);
408 }
409 TEST_SUITE_END() // S16
410 
411 TEST_SUITE(S8)
412 FIXTURE_DATA_TEST_CASE(RunSmall, NEStackLayerFixture<char>, framework::DatasetMode::ALL,
413  combine(combine(shapes_4d_small,
414  framework::dataset::make("DataType", { DataType::S8 })),
415  n_values))
416 {
417  // Validate output
418  validate(Accessor(_target), _reference);
419 }
420 
422  combine(combine(shapes_4d_large,
423  framework::dataset::make("DataType", { DataType::S8 })),
424  n_values))
425 {
426  // Validate output
427  validate(Accessor(_target), _reference);
428 }
429 TEST_SUITE_END() // S8
430 TEST_SUITE_END() // Shapes4D
431 TEST_SUITE_END() // StackLayer
432 TEST_SUITE_END() // NEON
433 } // namespace validation
434 } // namespace test
435 } // namespace arm_compute
Shape of a tensor.
Definition: TensorShape.h:39
TensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: CLTensor.cpp:41
bool is_resizable() const override
Flag indicating whether the size of the tensor can be changed.
Definition: TensorInfo.h:285
TensorShape compute_stack_shape(const ITensorInfo &a, unsigned int axis, unsigned int num_tensors)
Calculate the stack output shape of a tensor.
1 channel, 1 U8 per channel
1 channel, 1 F32 per channel
ARM_COMPUTE_EXPECT(has_error==expected, framework::LogLevel::ERRORS)
std::enable_if< is_container< T >::value, ContainerDataset< T > >::type make(std::string name, T &&values)
Helper function to create a ContainerDataset.
Copyright (c) 2017-2020 ARM Limited.
1 channel, 1 F16 per channel
1 channel, 1 S32 per channel
void validate_configuration(const CLTensor &src, TensorShape shape)
T wrap_around(T x, T m)
Wrap-around a number within the range 0 <= x < m.
Definition: Helpers.h:764
Accessor implementation for Tensor objects.
Definition: Accessor.h:35
DatasetMode
Possible dataset modes.
Definition: DatasetModes.h:40
StackLayerValidationFixture< Tensor, ITensor, Accessor, NEStackLayer, T > NEStackLayerFixture
Fixture to use.
Definition: StackLayer.cpp:113
quantized, asymmetric fixed-point 8-bit number unsigned
1 channel, 1 S16 per channel
FIXTURE_DATA_TEST_CASE(RunSmall, CLAbsLayerFixture< half >, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F16)))
Definition: AbsLayer.cpp:50
validate(dst.info() ->valid_region(), valid_region)
TEST_SUITE_END() FIXTURE_DATA_TEST_CASE(RunSmall
Input data sets.
static Status validate(const std::vector< ITensorInfo * > &input, int axis, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEStackLayerKernel.
Store the tensor's metadata.
Definition: TensorInfo.h:45
zip(zip(framework::dataset::make("Weights", { TensorInfo(TensorShape(32U, 13U, 2U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U, 1U), 1, DataType::F32), }), framework::dataset::make("MVBGInfo",{ TensorInfo(TensorShape(2U), 1, DataType::F32), TensorInfo(TensorShape(2U), 1, DataType::F16), TensorInfo(TensorShape(5U), 1, DataType::F32), })), framework::dataset::make("Expected", { true, false, false}))
DataType
Available data types.
Definition: Types.h:75
signed 8-bit number
combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)))
Definition: AbsLayer.cpp:65
TEST_SUITE(U8_to_S8) DATA_TEST_CASE(Configuration
cast configure & src
Definition: Cast.cpp:169
DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), AbsoluteDifferenceU8Dataset), shape, data_type0, data_type1, output_data_type)