blob: e8790c3ae25be6fb6f1f3f1efd0223d41facbee6 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
arovir0143095f32018-10-09 18:04:24 +01005
6#include <armnn/test/CreateWorkloadClNeon.hpp>
7
8#include <backends/MemCopyWorkload.hpp>
David Beck0dbe0ee2018-09-24 15:59:27 +01009#include <backends/neon/NeonWorkloadFactory.hpp>
10#include <backends/neon/NeonTensorHandle.hpp>
11#include <backends/neon/workloads/NeonWorkloadUtils.hpp>
12#include <backends/neon/workloads/NeonWorkloads.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
14BOOST_AUTO_TEST_SUITE(CreateWorkloadNeon)
15
16namespace
17{
18
19bool TestNeonTensorHandleInfo(armnn::INeonTensorHandle* handle, const armnn::TensorInfo& expectedInfo)
20{
21 using namespace armnn::armcomputetensorutils;
22
23 const arm_compute::ITensorInfo* handleInfo = handle->GetTensor().info();
24 const arm_compute::TensorInfo expectedAclInfo = BuildArmComputeTensorInfo(expectedInfo);
25
26 if (handleInfo->data_type() != expectedAclInfo.data_type())
27 {
28 return false;
29 }
30
31 if (handleInfo->num_dimensions() != expectedAclInfo.num_dimensions())
32 {
33 return false;
34 }
35
36 if (handleInfo->quantization_info() != expectedAclInfo.quantization_info())
37 {
38 return false;
39 }
40
41 for (std::size_t d = 0; d < expectedAclInfo.num_dimensions(); ++d)
42 {
43 if (handleInfo->dimension(d) != expectedAclInfo.dimension(d))
44 {
45 return false;
46 }
47 }
48
49 return true;
50}
51
52} // namespace
53
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010054template <typename armnn::DataType DataType>
telsoa01c577f2c2018-08-31 09:22:23 +010055static void NeonCreateActivationWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +000056{
57 Graph graph;
58 NeonWorkloadFactory factory;
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010059 auto workload = CreateActivationWorkloadTest<NeonActivationWorkload, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +000060
telsoa01c577f2c2018-08-31 09:22:23 +010061 // Checks that inputs/outputs are as we expect them (see definition of CreateActivationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +000062 ActivationQueueDescriptor queueDescriptor = workload->GetData();
63 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
64 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +010065 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({1, 1}, DataType)));
66 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +000067}
68
telsoa01c577f2c2018-08-31 09:22:23 +010069#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
70BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload)
71{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010072 NeonCreateActivationWorkloadTest<DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +010073}
74#endif
75
arovir019e53a352018-08-31 15:26:35 +010076BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +010077{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010078 NeonCreateActivationWorkloadTest<DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +010079}
80
David Beckbc392452018-09-10 14:47:28 +010081template <typename WorkloadType,
82 typename DescriptorType,
83 typename LayerType,
84 armnn::DataType DataType>
85static void NeonCreateArithmethicWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +000086{
David Beckbc392452018-09-10 14:47:28 +010087 Graph graph;
telsoa014fcda012018-03-09 14:13:49 +000088 NeonWorkloadFactory factory;
David Beckbc392452018-09-10 14:47:28 +010089 auto workload = CreateArithmeticWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +000090
David Beckbc392452018-09-10 14:47:28 +010091 DescriptorType queueDescriptor = workload->GetData();
telsoa014fcda012018-03-09 14:13:49 +000092 auto inputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
93 auto inputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[1]);
94 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +010095 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle1, TensorInfo({2, 3}, DataType)));
96 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle2, TensorInfo({2, 3}, DataType)));
97 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +000098}
99
telsoa01c577f2c2018-08-31 09:22:23 +0100100#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
101BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload)
102{
David Beckbc392452018-09-10 14:47:28 +0100103 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
104 AdditionQueueDescriptor,
105 AdditionLayer,
106 DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100107}
108#endif
109
arovir019e53a352018-08-31 15:26:35 +0100110BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100111{
David Beckbc392452018-09-10 14:47:28 +0100112 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
113 AdditionQueueDescriptor,
114 AdditionLayer,
115 DataType::Float32>();
116}
117
118#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
119BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload)
120{
121 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
122 SubtractionQueueDescriptor,
123 SubtractionLayer,
124 DataType::Float16>();
125}
126#endif
127
128BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
129{
130 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
131 SubtractionQueueDescriptor,
132 SubtractionLayer,
133 DataType::Float32>();
134}
135
136#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
137BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16Workload)
138{
139 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
140 MultiplicationQueueDescriptor,
141 MultiplicationLayer,
142 DataType::Float16>();
143}
144#endif
145
146BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkload)
147{
148 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
149 MultiplicationQueueDescriptor,
150 MultiplicationLayer,
151 DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100152}
153
154template <typename BatchNormalizationWorkloadType, typename armnn::DataType DataType>
155static void NeonCreateBatchNormalizationWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000156{
157 Graph graph;
158 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100159 auto workload = CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000160
telsoa01c577f2c2018-08-31 09:22:23 +0100161 // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000162 BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
163 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
164 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100165 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({2, 3, 1, 1}, DataType)));
166 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3, 1, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000167}
168
telsoa01c577f2c2018-08-31 09:22:23 +0100169#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
170BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16Workload)
171{
arovir019e53a352018-08-31 15:26:35 +0100172 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100173}
174#endif
175
arovir019e53a352018-08-31 15:26:35 +0100176BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100177{
arovir019e53a352018-08-31 15:26:35 +0100178 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100179}
180
181template <typename Convolution2dWorkloadType, typename armnn::DataType DataType>
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100182static void NeonCreateConvolution2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
telsoa014fcda012018-03-09 14:13:49 +0000183{
184 Graph graph;
185 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100186 auto workload = CreateConvolution2dWorkloadTest<Convolution2dWorkloadType,
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100187 DataType>(factory, graph, dataLayout);
188
189 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
190 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
telsoa014fcda012018-03-09 14:13:49 +0000191
telsoa01c577f2c2018-08-31 09:22:23 +0100192 // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000193 Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
194 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
195 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100196 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
197 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000198}
199
telsoa01c577f2c2018-08-31 09:22:23 +0100200#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100201BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100202{
arovir019e53a352018-08-31 15:26:35 +0100203 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100204}
telsoa01c577f2c2018-08-31 09:22:23 +0100205
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100206BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NhwcWorkload)
207{
208 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float16>(DataLayout::NHWC);
209}
210
211#endif
212BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100213{
arovir019e53a352018-08-31 15:26:35 +0100214 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100215}
216
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100217BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
218{
219 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float32>(DataLayout::NHWC);
220}
221
Nikhil Rajcec6b652018-10-12 13:51:57 +0100222template <typename DepthwiseConvolution2dFloat32WorkloadType, typename armnn::DataType DataType>
223static void NeonCreateDepthWiseConvolutionWorkloadTest(DataLayout dataLayout)
224{
225 Graph graph;
226 NeonWorkloadFactory factory;
227
228 auto workload = CreateDepthwiseConvolution2dWorkloadTest<DepthwiseConvolution2dFloat32WorkloadType,
229 DataType>(factory, graph, dataLayout);
230
231 // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
232 DepthwiseConvolution2dQueueDescriptor queueDescriptor = workload->GetData();
233 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
234 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
235
236 std::initializer_list<unsigned int> inputShape = (dataLayout == DataLayout::NCHW)
237 ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
238 : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
239 std::initializer_list<unsigned int> outputShape = (dataLayout == DataLayout::NCHW)
240 ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
241 : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
242
243 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
244 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
245}
246
247BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat32NhwcWorkload)
248{
249 NeonCreateDepthWiseConvolutionWorkloadTest<NeonDepthwiseConvolutionFloatWorkload,
250 DataType::Float32>(DataLayout::NHWC);
251}
252
253#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
254BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat16NhwcWorkload)
255{
256 NeonCreateDepthWiseConvolutionWorkloadTest<NeonDepthwiseConvolutionFloatWorkload,
257 DataType::Float16>(DataLayout::NHWC);
258}
259#endif
260
telsoa01c577f2c2018-08-31 09:22:23 +0100261template <typename FullyConnectedWorkloadType, typename armnn::DataType DataType>
262static void NeonCreateFullyConnectedWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000263{
264 Graph graph;
265 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100266 auto workload = CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType,
267 DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000268
telsoa01c577f2c2018-08-31 09:22:23 +0100269 // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000270 FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
271 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
272 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100273 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 1, 4, 5}, DataType)));
274 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 7}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000275}
276
telsoa01c577f2c2018-08-31 09:22:23 +0100277#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
278BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16Workload)
279{
kevmay01e448be32018-09-26 10:21:55 +0100280 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100281}
282#endif
283
arovir019e53a352018-08-31 15:26:35 +0100284BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100285{
kevmay01e448be32018-09-26 10:21:55 +0100286 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100287}
288
telsoa01c577f2c2018-08-31 09:22:23 +0100289template <typename NormalizationWorkloadType, typename armnn::DataType DataType>
narpra0155a97bc2018-10-02 14:35:53 +0100290static void NeonCreateNormalizationWorkloadTest(DataLayout dataLayout)
telsoa014fcda012018-03-09 14:13:49 +0000291{
narpra0155a97bc2018-10-02 14:35:53 +0100292 Graph graph;
telsoa014fcda012018-03-09 14:13:49 +0000293 NeonWorkloadFactory factory;
narpra0155a97bc2018-10-02 14:35:53 +0100294 auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000295
telsoa01c577f2c2018-08-31 09:22:23 +0100296 // Checks that outputs and inputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000297 NormalizationQueueDescriptor queueDescriptor = workload->GetData();
298 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
299 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100300 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 5, 5, 1}, DataType)));
301 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 5, 5, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000302}
303
telsoa01c577f2c2018-08-31 09:22:23 +0100304#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
narpra0155a97bc2018-10-02 14:35:53 +0100305BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100306{
narpra0155a97bc2018-10-02 14:35:53 +0100307 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
308}
309
310BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NhwcWorkload)
311{
312 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
telsoa01c577f2c2018-08-31 09:22:23 +0100313}
314#endif
315
narpra0155a97bc2018-10-02 14:35:53 +0100316BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100317{
narpra0155a97bc2018-10-02 14:35:53 +0100318 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
telsoa01c577f2c2018-08-31 09:22:23 +0100319}
320
narpra0155a97bc2018-10-02 14:35:53 +0100321BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNhwcWorkload)
322{
323 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
324}
325
326
telsoa01c577f2c2018-08-31 09:22:23 +0100327template <typename Pooling2dWorkloadType, typename armnn::DataType DataType>
Nina Drozdb48e6862018-10-09 12:09:56 +0100328static void NeonCreatePooling2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
telsoa014fcda012018-03-09 14:13:49 +0000329{
330 Graph graph;
331 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100332 auto workload = CreatePooling2dWorkloadTest<Pooling2dWorkloadType, DataType>
Nina Drozdb48e6862018-10-09 12:09:56 +0100333 (factory, graph, dataLayout);
334
335 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 5, 5} : TensorShape{3, 5, 5, 2};
336 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 2, 4} : TensorShape{3, 2, 4, 2};
telsoa014fcda012018-03-09 14:13:49 +0000337
telsoa01c577f2c2018-08-31 09:22:23 +0100338 // Checks that outputs and inputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000339 Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
340 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
341 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Nina Drozdb48e6862018-10-09 12:09:56 +0100342 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
343 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000344}
345
telsoa01c577f2c2018-08-31 09:22:23 +0100346#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
347BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16Workload)
348{
arovir019e53a352018-08-31 15:26:35 +0100349 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100350}
351#endif
352
Nina Drozdb48e6862018-10-09 12:09:56 +0100353BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100354{
Nina Drozdb48e6862018-10-09 12:09:56 +0100355 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float32>(DataLayout::NCHW);
telsoa01c577f2c2018-08-31 09:22:23 +0100356}
357
Nina Drozdb48e6862018-10-09 12:09:56 +0100358BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNhwcWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100359{
Nina Drozdb48e6862018-10-09 12:09:56 +0100360 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float32>(DataLayout::NHWC);
361}
362
363BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NchwWorkload)
364{
365 NeonCreatePooling2dWorkloadTest<NeonPooling2dUint8Workload, DataType::QuantisedAsymm8>(DataLayout::NCHW);
366}
367
368BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NhwcWorkload)
369{
370 NeonCreatePooling2dWorkloadTest<NeonPooling2dUint8Workload, DataType::QuantisedAsymm8>(DataLayout::NHWC);
telsoa01c577f2c2018-08-31 09:22:23 +0100371}
372
Nattapat Chaimanowongcce11fc2018-10-12 16:30:56 +0100373template <typename armnn::DataType DataType>
telsoa01c577f2c2018-08-31 09:22:23 +0100374static void NeonCreateReshapeWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000375{
376 Graph graph;
377 NeonWorkloadFactory factory;
Nattapat Chaimanowongcce11fc2018-10-12 16:30:56 +0100378 auto workload = CreateReshapeWorkloadTest<NeonReshapeWorkload, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000379
telsoa01c577f2c2018-08-31 09:22:23 +0100380 // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000381 ReshapeQueueDescriptor queueDescriptor = workload->GetData();
382 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
383 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100384 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
385 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 4}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000386}
387
telsoa01c577f2c2018-08-31 09:22:23 +0100388#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
389BOOST_AUTO_TEST_CASE(CreateReshapeFloat16Workload)
390{
Nattapat Chaimanowongcce11fc2018-10-12 16:30:56 +0100391 NeonCreateReshapeWorkloadTest<DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100392}
393#endif
394
arovir019e53a352018-08-31 15:26:35 +0100395BOOST_AUTO_TEST_CASE(CreateReshapeFloatWorkload)
telsoa014fcda012018-03-09 14:13:49 +0000396{
Nattapat Chaimanowongcce11fc2018-10-12 16:30:56 +0100397 NeonCreateReshapeWorkloadTest<DataType::Float32>();
telsoa014fcda012018-03-09 14:13:49 +0000398}
399
400BOOST_AUTO_TEST_CASE(CreateReshapeUint8Workload)
401{
Nattapat Chaimanowongcce11fc2018-10-12 16:30:56 +0100402 NeonCreateReshapeWorkloadTest<DataType::QuantisedAsymm8>();
telsoa014fcda012018-03-09 14:13:49 +0000403}
404
telsoa01c577f2c2018-08-31 09:22:23 +0100405template <typename SoftmaxWorkloadType, typename armnn::DataType DataType>
406static void NeonCreateSoftmaxWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000407{
408 Graph graph;
409 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100410 auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000411
telsoa01c577f2c2018-08-31 09:22:23 +0100412 // Checks that outputs and inputs are as we expect them (see definition of CreateSoftmaxWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000413 SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
414 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
415 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100416 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
417 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({4, 1}, DataType)));
418}
419
420#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
421BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat16Workload)
422{
arovir019e53a352018-08-31 15:26:35 +0100423 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100424}
425#endif
426
arovir019e53a352018-08-31 15:26:35 +0100427BOOST_AUTO_TEST_CASE(CreateSoftmaxFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100428{
arovir019e53a352018-08-31 15:26:35 +0100429 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float32>();
telsoa014fcda012018-03-09 14:13:49 +0000430}
431
432BOOST_AUTO_TEST_CASE(CreateSplitterWorkload)
433{
434 Graph graph;
435 NeonWorkloadFactory factory;
Nattapat Chaimanowong14766d72018-10-12 15:09:53 +0100436 auto workload = CreateSplitterWorkloadTest<NeonSplitterWorkload, DataType::Float32>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000437
telsoa01c577f2c2018-08-31 09:22:23 +0100438 // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000439 SplitterQueueDescriptor queueDescriptor = workload->GetData();
440 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
surmeh013537c2c2018-05-18 16:31:43 +0100441 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({5, 7, 7}, DataType::Float32)));
442
telsoa014fcda012018-03-09 14:13:49 +0000443 auto outputHandle0 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
surmeh013537c2c2018-05-18 16:31:43 +0100444 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle0, TensorInfo({1, 7, 7}, DataType::Float32)));
445
telsoa014fcda012018-03-09 14:13:49 +0000446 auto outputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[1]);
surmeh013537c2c2018-05-18 16:31:43 +0100447 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle1, TensorInfo({2, 7, 7}, DataType::Float32)));
448
telsoa014fcda012018-03-09 14:13:49 +0000449 auto outputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[2]);
surmeh013537c2c2018-05-18 16:31:43 +0100450 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle2, TensorInfo({2, 7, 7}, DataType::Float32)));
telsoa014fcda012018-03-09 14:13:49 +0000451}
452
453BOOST_AUTO_TEST_CASE(CreateSplitterMerger)
454{
telsoa01c577f2c2018-08-31 09:22:23 +0100455 // Tests that it is possible to decide which output of the splitter layer
456 // should be lined to which input of the merger layer.
457 // We tested that is is possible to specify 0th output
458 // of the splitter to be the 1st input to the merger, and the 1st output of the splitter to be 0th input
telsoa014fcda012018-03-09 14:13:49 +0000459 // of the merger.
460
461 Graph graph;
462 NeonWorkloadFactory factory;
463
464 auto workloads =
Nattapat Chaimanowong14766d72018-10-12 15:09:53 +0100465 CreateSplitterMergerWorkloadTest<NeonSplitterWorkload, NeonMergerWorkload,
telsoa01c577f2c2018-08-31 09:22:23 +0100466 DataType::Float32>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000467
468 auto wlSplitter = std::move(workloads.first);
469 auto wlMerger = std::move(workloads.second);
470
telsoa01c577f2c2018-08-31 09:22:23 +0100471 //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
telsoa014fcda012018-03-09 14:13:49 +0000472 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
473 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
474 armnn::INeonTensorHandle* mIn0 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[0]);
475 armnn::INeonTensorHandle* mIn1 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[1]);
476
477 BOOST_TEST(sOut0);
478 BOOST_TEST(sOut1);
479 BOOST_TEST(mIn0);
480 BOOST_TEST(mIn1);
481
482 bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
483
484 BOOST_TEST(validDataPointers);
485}
486
487BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputs)
488{
telsoa01c577f2c2018-08-31 09:22:23 +0100489 // Tests that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
490 // We created a splitter with two outputs. That each of those outputs is used by two different activation layers
telsoa014fcda012018-03-09 14:13:49 +0000491
492 Graph graph;
493 NeonWorkloadFactory factory;
Nattapat Chaimanowong14766d72018-10-12 15:09:53 +0100494 std::unique_ptr<NeonSplitterWorkload> wlSplitter;
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100495 std::unique_ptr<NeonActivationWorkload> wlActiv0_0;
496 std::unique_ptr<NeonActivationWorkload> wlActiv0_1;
497 std::unique_ptr<NeonActivationWorkload> wlActiv1_0;
498 std::unique_ptr<NeonActivationWorkload> wlActiv1_1;
telsoa014fcda012018-03-09 14:13:49 +0000499
Nattapat Chaimanowong14766d72018-10-12 15:09:53 +0100500 CreateSplitterMultipleInputsOneOutputWorkloadTest<NeonSplitterWorkload,
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100501 NeonActivationWorkload, DataType::Float32>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1,
502 wlActiv1_0, wlActiv1_1);
telsoa014fcda012018-03-09 14:13:49 +0000503
504 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
505 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
506 armnn::INeonTensorHandle* activ0_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
507 armnn::INeonTensorHandle* activ0_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
508 armnn::INeonTensorHandle* activ1_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
509 armnn::INeonTensorHandle* activ1_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
510
511
512 BOOST_TEST(sOut0);
513 BOOST_TEST(sOut1);
514 BOOST_TEST(activ0_0Im);
515 BOOST_TEST(activ0_1Im);
516 BOOST_TEST(activ1_0Im);
517 BOOST_TEST(activ1_1Im);
518
519 bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
520 (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
521
522 BOOST_TEST(validDataPointers);
523}
524
525BOOST_AUTO_TEST_CASE(CreateMemCopyWorkloadsNeon)
526{
527 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100528 CreateMemCopyWorkloads<INeonTensorHandle>(factory);
telsoa014fcda012018-03-09 14:13:49 +0000529}
530
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100531template <typename L2NormalizationWorkloadType, typename armnn::DataType DataType>
532static void NeonCreateL2NormalizationWorkloadTest(DataLayout dataLayout)
533{
Matteo Martincigh2400b6d2018-10-09 18:19:20 +0100534 Graph graph;
535 NeonWorkloadFactory factory;
536 auto workload =
537 CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100538
539 // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
540 L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
541 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
542 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Matteo Martincigh2400b6d2018-10-09 18:19:20 +0100543
544 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
545 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
546 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
547 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
548
549 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
550 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100551}
552
553#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
554BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NchwWorkload)
555{
556 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
557}
558
559BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NhwcWorkload)
560{
561 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
562}
563#endif
564
565BOOST_AUTO_TEST_CASE(CreateL2NormalizationNchwWorkload)
566{
567 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
568}
569
570BOOST_AUTO_TEST_CASE(CreateL2NormalizationNhwcWorkload)
571{
572 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
573}
574
telsoa014fcda012018-03-09 14:13:49 +0000575BOOST_AUTO_TEST_SUITE_END()