ArmNN
 23.02
CreateWorkload.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "TestUtils.hpp"
8 
9 #include <Graph.hpp>
10 #include <Network.hpp>
11 #include <ResolveType.hpp>
12 
17 #include <armnn/utility/Assert.hpp>
20 
21 #include <doctest/doctest.h>
22 
23 #include <utility>
24 
25 using namespace armnn;
26 
27 namespace
28 {
29 
30 using namespace std;
31 
32 // Calls CreateWorkload for a layer, and checks the returned pointer is of the correct type.
33 template<typename Workload>
34 std::unique_ptr<Workload> MakeAndCheckWorkload(Layer& layer,
35  const IWorkloadFactory& factory,
36  const ModelOptions& modelOptions = {})
37 {
38  std::unique_ptr<IWorkload> workload = layer.CreateWorkload(factory);
39  CHECK_MESSAGE(workload.get() == PolymorphicDowncast<Workload*>(workload.get()),
40  "Cannot convert to derived class");
41  std::string reasonIfUnsupported;
42  layer.SetBackendId(factory.GetBackendId());
43  CHECK(factory.IsLayerSupported(layer, layer.GetDataType(), reasonIfUnsupported, modelOptions));
44  return std::unique_ptr<Workload>(static_cast<Workload*>(workload.release()));
45 }
46 
47 // Helper function to create tensor handlers for workloads, assuming they all use the same factory.
48 void CreateTensorHandles(armnn::Graph& graph,
49  armnn::IWorkloadFactory& factory)
50 {
51  TensorHandleFactoryRegistry tmpRegistry;
52  for (auto&& layer : graph.TopologicalSort())
53  {
54  layer->CreateTensorHandles(tmpRegistry, factory);
55  }
56 }
57 
58 /////////////////////////////////////////////////////////////////////////////////////////////
59 // The following functions are called by backendsCommon/test/CreateWorkload*.cpp
60 // They build very simple graphs, and then create a workload.
61 // Some checks are performed on the workload to ensure parameters have been passed correctly.
62 // They return the created workloads so that backend-specific checks can be performed.
63 /////////////////////////////////////////////////////////////////////////////////////////////
64 
65 template <typename ActivationWorkload, armnn::DataType DataType>
66 std::unique_ptr<ActivationWorkload> CreateActivationWorkloadTest(armnn::IWorkloadFactory& factory,
67  armnn::Graph& graph)
68 {
69  // Creates the layer we're testing.
70  ActivationDescriptor layerDesc;
72  layerDesc.m_A = 3.5f;
73  layerDesc.m_B = -10.0f;
74 
75  ActivationLayer* const layer = graph.AddLayer<ActivationLayer>(layerDesc, "layer");
76 
77  // Creates extra layers.
78  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
79  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
80 
81  // Connects up.
82  armnn::TensorInfo tensorInfo({1, 1}, DataType);
83 
84  Connect(input, layer, tensorInfo);
85  Connect(layer, output, tensorInfo);
86 
87  CreateTensorHandles(graph, factory);
88 
89  // Makes the workload and checks it.
90  auto workload = MakeAndCheckWorkload<ActivationWorkload>(*layer, factory);
91 
92  ActivationQueueDescriptor queueDescriptor = workload->GetData();
93  CHECK(queueDescriptor.m_Inputs.size() == 1);
94  CHECK(queueDescriptor.m_Outputs.size() == 1);
95  CHECK(queueDescriptor.m_Parameters.m_A == 3.5f);
96  CHECK(queueDescriptor.m_Parameters.m_B == -10.0f);
97  CHECK((queueDescriptor.m_Parameters.m_Function == ActivationFunction::ReLu));
98 
99  // Returns so we can do extra, backend-specific tests.
100  return workload;
101 }
102 
103 template <typename WorkloadType,
104  typename DescriptorType,
105  typename LayerType,
107 std::unique_ptr<WorkloadType> CreateElementwiseWorkloadTest(armnn::IWorkloadFactory & factory,
108  armnn::Graph & graph)
109 {
110  // Creates the layer we're testing.
111  Layer* const layer = graph.AddLayer<LayerType>("layer");
112 
113  // Creates extra layers.
114  Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
115  Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
116  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
117 
118  // Connects up.
119  armnn::TensorInfo tensorInfo({2, 3}, DataType);
120  Connect(input1, layer, tensorInfo, 0, 0);
121  Connect(input2, layer, tensorInfo, 0, 1);
122  Connect(layer, output, tensorInfo);
123  CreateTensorHandles(graph, factory);
124 
125  // Makes the workload and checks it.
126  auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
127 
128  DescriptorType queueDescriptor = workload->GetData();
129  CHECK(queueDescriptor.m_Inputs.size() == 2);
130  CHECK(queueDescriptor.m_Outputs.size() == 1);
131 
132  // Returns so we can do extra, backend-specific tests.
133  return workload;
134 }
135 
136 template<typename WorkloadType,
137  typename DescriptorType,
139 std::unique_ptr<WorkloadType> CreateSubtractionWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
140  armnn::Graph& graph)
141 {
142  // Creates the layer we're testing.
143  SubtractionLayer* const layer = graph.AddLayer<SubtractionLayer>("layer");
144 
145  auto activationDesc = std::make_shared<ActivationDescriptor>();
146  activationDesc->m_A = 10.0f;
147  activationDesc->m_B = 5.0f;
148  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
149 
150  layer->SetAdditionalInfoForObject(activationDesc);
151 
152  // Creates extra layers.
153  Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
154  Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
155  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
156 
157  // Connects up.
158  armnn::TensorInfo tensorInfo({2, 3}, DataType);
159  Connect(input1, layer, tensorInfo, 0, 0);
160  Connect(input2, layer, tensorInfo, 0, 1);
161  Connect(layer, output, tensorInfo);
162  CreateTensorHandles(graph, factory);
163 
164  // Check that the additional information can be queried from the layer
165  std::shared_ptr<ActivationDescriptor>
166  activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
167 
168  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
169  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
170  ARMNN_ASSERT(
171  static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
172  );
173 
174  // Makes the workload and checks it.
175  auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
176 
177  DescriptorType queueDescriptor = workload->GetData();
178 
179  const ActivationDescriptor* queueDescBlobPtr =
180  queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
181  IgnoreUnused(queueDescBlobPtr);
182  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
183  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
184  ARMNN_ASSERT(
185  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
186  );
187 
188  CHECK(queueDescriptor.m_Inputs.size() == 2);
189  CHECK(queueDescriptor.m_Outputs.size() == 1);
190 
191  return workload;
192 }
193 
194 template<typename WorkloadType,
195  typename DescriptorType,
197 std::unique_ptr<WorkloadType> CreateMultiplicationWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
198  armnn::Graph& graph)
199 {
200  // Creates the layer we're testing.
201  MultiplicationLayer* const layer = graph.AddLayer<MultiplicationLayer>("layer");
202 
203  auto activationDesc = std::make_shared<ActivationDescriptor>();
204  activationDesc->m_A = 10.0f;
205  activationDesc->m_B = 5.0f;
206  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
207 
208  layer->SetAdditionalInfoForObject(activationDesc);
209 
210  // Creates extra layers.
211  Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
212  Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
213  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
214 
215  // Connects up.
216  armnn::TensorInfo tensorInfo({2, 3}, DataType);
217  Connect(input1, layer, tensorInfo, 0, 0);
218  Connect(input2, layer, tensorInfo, 0, 1);
219  Connect(layer, output, tensorInfo);
220  CreateTensorHandles(graph, factory);
221 
222  // Check that the additional information can be queried from the layer
223  std::shared_ptr<ActivationDescriptor>
224  activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
225 
226  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
227  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
228  ARMNN_ASSERT(
229  static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
230  );
231 
232  // Makes the workload and checks it.
233  auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
234 
235  DescriptorType queueDescriptor = workload->GetData();
236  CHECK(queueDescriptor.m_Inputs.size() == 2);
237  CHECK(queueDescriptor.m_Outputs.size() == 1);
238  const ActivationDescriptor* queueDescBlobPtr =
239  queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
240  IgnoreUnused(queueDescBlobPtr);
241  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
242  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
243  ARMNN_ASSERT(
244  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
245  );
246 
247  return workload;// Returns so we can do extra, backend-specific tests.
248 }
249 
250 template<typename WorkloadType,
251  typename DescriptorType,
253 std::unique_ptr<WorkloadType> CreateAdditionWithBlobWorkloadTest(armnn::IWorkloadFactory& factory,
254  armnn::Graph& graph)
255 {
256  // Creates the layer we're testing.
257  AdditionLayer* const layer = graph.AddLayer<AdditionLayer>("layer");
258 
259  auto activationDesc = std::make_shared<ActivationDescriptor>();
260  activationDesc->m_A = 10.0f;
261  activationDesc->m_B = 5.0f;
262  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
263 
264  layer->SetAdditionalInfoForObject(activationDesc);
265 
266  // Creates extra layers.
267  Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
268  Layer* const input2 = graph.AddLayer<InputLayer>(2, "input2");
269  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
270 
271  // Connects up.
272  armnn::TensorInfo tensorInfo({2, 3}, DataType);
273  Connect(input1, layer, tensorInfo, 0, 0);
274  Connect(input2, layer, tensorInfo, 0, 1);
275  Connect(layer, output, tensorInfo);
276  CreateTensorHandles(graph, factory);
277 
278  // Check that the additional information can be queried from the layer
279  std::shared_ptr<ActivationDescriptor>
280  activationDescPtr = layer->template GetAdditionalInformation<ActivationDescriptor>();
281 
282  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
283  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
284  ARMNN_ASSERT(
285  static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
286  );
287 
288  // Makes the workload and checks it.
289  auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
290 
291  DescriptorType queueDescriptor = workload->GetData();
292  const ActivationDescriptor* queueDescBlobPtr =
293  queueDescriptor.template GetAdditionalInformation<ActivationDescriptor>();
294  IgnoreUnused(queueDescBlobPtr);
295  CHECK(queueDescriptor.m_Inputs.size() == 2);
296  CHECK(queueDescriptor.m_Outputs.size() == 1);
297  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
298  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
299  ARMNN_ASSERT(
300  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
301  );
302 
303  return workload;
304 }
305 
306 template <typename WorkloadType,
307  typename DescriptorType,
309 std::unique_ptr<WorkloadType> CreateElementwiseUnaryWorkloadTest(armnn::IWorkloadFactory & factory,
310  armnn::Graph & graph,
312 {
314  Layer* const layer = graph.AddLayer<armnn::ElementwiseUnaryLayer>(desc, "layer");
315 
316  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
317  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
318 
319  armnn::TensorInfo tensorInfo({ 2, 3 }, DataType);
320  Connect(input, layer, tensorInfo, 0, 0);
321  Connect(layer, output, tensorInfo, 0, 0);
322  CreateTensorHandles(graph, factory);
323 
324  auto workload = MakeAndCheckWorkload<WorkloadType>(*layer, factory);
325  DescriptorType queueDescriptor = workload->GetData();
326 
327  CHECK(queueDescriptor.m_Inputs.size() == 1);
328  CHECK(queueDescriptor.m_Outputs.size() == 1);
329 
330  return workload;
331 }
332 
333 template <typename BatchNormalizationWorkloadType, armnn::DataType DataType>
334 std::unique_ptr<BatchNormalizationWorkloadType> CreateBatchNormalizationWorkloadTest(
335  armnn::IWorkloadFactory& factory, armnn::Graph& graph, DataLayout dataLayout = DataLayout::NCHW)
336 {
337  TensorShape tensorShape;
338  switch (dataLayout)
339  {
340  case DataLayout::NHWC:
341  tensorShape = { 2, 4, 4, 3 };
342  break;
343  case DataLayout::NCHW:
344  default:
345  tensorShape = { 2, 3, 4, 4 };
346  }
347 
348  // Creates the layer we're testing.
350  layerDesc.m_Eps = 0.05f;
351  layerDesc.m_DataLayout = dataLayout;
352 
353  BatchNormalizationLayer* const layer = graph.AddLayer<BatchNormalizationLayer>(layerDesc, "layer");
354 
355  armnn::TensorInfo weightInfo({3}, DataType);
356  layer->m_Mean = std::make_unique<ScopedTensorHandle>(weightInfo);
357  layer->m_Variance = std::make_unique<ScopedTensorHandle>(weightInfo);
358  layer->m_Beta = std::make_unique<ScopedTensorHandle>(weightInfo);
359  layer->m_Gamma = std::make_unique<ScopedTensorHandle>(weightInfo);
360  layer->m_Mean->Allocate();
361  layer->m_Variance->Allocate();
362  layer->m_Beta->Allocate();
363  layer->m_Gamma->Allocate();
364 
365  // Creates extra layers.
366  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
367  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
368 
369  // Connects up.
370  armnn::TensorInfo tensorInfo(tensorShape, DataType);
371  Connect(input, layer, tensorInfo);
372  Connect(layer, output, tensorInfo);
373  CreateTensorHandles(graph, factory);
374 
375  // Makes the workload and checks it.
376  auto workload = MakeAndCheckWorkload<BatchNormalizationWorkloadType>(*layer, factory);
377  BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
378  CHECK(queueDescriptor.m_Parameters.m_Eps == 0.05f);
379  CHECK(queueDescriptor.m_Inputs.size() == 1);
380  CHECK(queueDescriptor.m_Outputs.size() == 1);
381  CHECK((queueDescriptor.m_Mean->GetTensorInfo() == TensorInfo({3}, DataType)));
382  CHECK((queueDescriptor.m_Variance->GetTensorInfo() == TensorInfo({3}, DataType)));
383  CHECK((queueDescriptor.m_Gamma->GetTensorInfo() == TensorInfo({3}, DataType)));
384  CHECK((queueDescriptor.m_Beta->GetTensorInfo() == TensorInfo({3}, DataType)));
385  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
386 
387  // Returns so we can do extra, backend-specific tests.
388  return workload;
389 }
390 
391 template <typename BatchNormalizationWorkloadType, armnn::DataType DataType>
392 std::unique_ptr<BatchNormalizationWorkloadType> CreateBatchNormalizationWithBlobWorkloadTest(
393  armnn::IWorkloadFactory& factory, armnn::Graph& graph, DataLayout dataLayout = DataLayout::NCHW)
394 {
395  TensorShape tensorShape;
396  switch (dataLayout)
397  {
398  case DataLayout::NHWC:
399  tensorShape = { 2, 4, 4, 3 };
400  break;
401  case DataLayout::NCHW:
402  default:
403  tensorShape = { 2, 3, 4, 4 };
404  }
405 
406  // Creates the layer we're testing.
408  layerDesc.m_Eps = 0.05f;
409  layerDesc.m_DataLayout = dataLayout;
410 
411  BatchNormalizationLayer* const layer = graph.AddLayer<BatchNormalizationLayer>(layerDesc, "layer");
412 
413  armnn::TensorInfo weightInfo({3}, DataType);
414  layer->m_Mean = std::make_unique<ScopedTensorHandle>(weightInfo);
415  layer->m_Variance = std::make_unique<ScopedTensorHandle>(weightInfo);
416  layer->m_Beta = std::make_unique<ScopedTensorHandle>(weightInfo);
417  layer->m_Gamma = std::make_unique<ScopedTensorHandle>(weightInfo);
418  layer->m_Mean->Allocate();
419  layer->m_Variance->Allocate();
420  layer->m_Beta->Allocate();
421  layer->m_Gamma->Allocate();
422 
423  auto activationDesc = std::make_shared<ActivationDescriptor>();
424  activationDesc->m_A = 10.0f;
425  activationDesc->m_B = 5.0f;
426  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
427 
428  layer->SetAdditionalInfoForObject(activationDesc);
429 
430  // Check that the additional information can be queried from the layer
431  std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
432  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
433  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
434  ARMNN_ASSERT(
435  static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
436  );
437 
438  // Creates extra layers.
439  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
440  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
441 
442  // Connects up.
443  armnn::TensorInfo tensorInfo(tensorShape, DataType);
444  Connect(input, layer, tensorInfo);
445  Connect(layer, output, tensorInfo);
446  CreateTensorHandles(graph, factory);
447 
448  // Makes the workload and checks it.
449  auto workload = MakeAndCheckWorkload<BatchNormalizationWorkloadType>(*layer, factory);
450  BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
451  const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
452  IgnoreUnused(queueDescBlobPtr);
453  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
454  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
455  ARMNN_ASSERT(
456  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
457  );
458 
459  CHECK(queueDescriptor.m_Parameters.m_Eps == 0.05f);
460  CHECK(queueDescriptor.m_Inputs.size() == 1);
461  CHECK(queueDescriptor.m_Outputs.size() == 1);
462  CHECK((queueDescriptor.m_Mean->GetTensorInfo() == TensorInfo({3}, DataType)));
463  CHECK((queueDescriptor.m_Variance->GetTensorInfo() == TensorInfo({3}, DataType)));
464  CHECK((queueDescriptor.m_Gamma->GetTensorInfo() == TensorInfo({3}, DataType)));
465  CHECK((queueDescriptor.m_Beta->GetTensorInfo() == TensorInfo({3}, DataType)));
466  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
467 
468  // Returns so we can do extra, backend-specific tests.
469  return workload;
470 }
471 
472 template <typename Convolution2dWorkload, armnn::DataType DataType>
473 std::unique_ptr<Convolution2dWorkload> CreateConvolution2dWorkloadTest(armnn::IWorkloadFactory& factory,
474  armnn::Graph& graph,
475  DataLayout dataLayout = DataLayout::NCHW,
476  const ModelOptions& modelOptions = {})
477 {
478  // Creates the layer we're testing.
479  Convolution2dDescriptor layerDesc;
480  layerDesc.m_PadLeft = 3;
481  layerDesc.m_PadRight = 3;
482  layerDesc.m_PadTop = 1;
483  layerDesc.m_PadBottom = 1;
484  layerDesc.m_StrideX = 2;
485  layerDesc.m_StrideY = 4;
486  layerDesc.m_BiasEnabled = false;
487  layerDesc.m_DataLayout = dataLayout;
488 
489  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
490  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
491 
492  Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
493 
494  TensorShape weightShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 5, 3} : TensorShape{2, 5, 3, 3};
495  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
496  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
497 
498  armnn::TensorInfo weightsTensorInfo(weightShape, DataType, inputsQScale);
499  weightsTensorInfo.SetConstant();
500 
501  // Creates extra layers.
502  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
503  auto const weights = graph.AddLayer<ConstantLayer>("weights");
504  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
505 
506  weights->m_LayerOutput = std::make_unique<ScopedTensorHandle>(weightsTensorInfo);
507  weights->m_LayerOutput->Allocate();
508 
509  // Connects up.
510  Connect(input, layer, TensorInfo(inputShape, DataType, inputsQScale));
511  Connect(weights, layer, weightsTensorInfo, 0, 1);
512  Connect(layer, output, TensorInfo(outputShape, DataType, outputQScale));
513  CreateTensorHandles(graph, factory);
514 
515  // Makes the workload and checks it.
516  auto workload = MakeAndCheckWorkload<Convolution2dWorkload>(*layer, factory, modelOptions);
517 
518  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
519  CHECK(queueDescriptor.m_Parameters.m_StrideX == 2);
520  CHECK(queueDescriptor.m_Parameters.m_StrideY == 4);
521  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 3);
522  CHECK(queueDescriptor.m_Parameters.m_PadRight == 3);
523  CHECK(queueDescriptor.m_Parameters.m_PadTop == 1);
524  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 1);
525  CHECK(!queueDescriptor.m_Parameters.m_BiasEnabled);
526  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
527 
528  CHECK(queueDescriptor.m_Inputs.size() == 2);
529  CHECK(queueDescriptor.m_Outputs.size() == 1);
530 
531  // Returns so we can do extra, backend-specific tests.
532  return workload;
533 }
534 
535 template<typename Convolution2dWorkload, armnn::DataType DataType>
536 std::unique_ptr<Convolution2dWorkload> CreateConvolution2dFusedActivationWithBlobWorkloadTest(
537  armnn::IWorkloadFactory& factory,
538  armnn::Graph& graph,
539  DataLayout dataLayout = DataLayout::NCHW,
540  const ModelOptions& modelOptions = {})
541 {
542  // Creates the layer we're testing.
543  Convolution2dDescriptor layerDesc;
544  layerDesc.m_PadLeft = 3;
545  layerDesc.m_PadRight = 3;
546  layerDesc.m_PadTop = 1;
547  layerDesc.m_PadBottom = 1;
548  layerDesc.m_StrideX = 2;
549  layerDesc.m_StrideY = 4;
550  layerDesc.m_BiasEnabled = true;
551  layerDesc.m_DataLayout = dataLayout;
552 
553  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
554  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
555 
556  Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
557 
558  TensorShape weightShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 5, 3} : TensorShape{2, 5, 3, 3};
559  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
560  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
561 
562  armnn::TensorInfo weightsTensorInfo(weightShape, DataType, inputsQScale);
563  weightsTensorInfo.SetConstant();
564  armnn::TensorInfo biasTensorInfo({2}, DataType, inputsQScale);
565  biasTensorInfo.SetConstant();
566 
567  auto activationDesc = std::make_shared<ActivationDescriptor>();
568  activationDesc->m_A = 10.0f;
569  activationDesc->m_B = 5.0f;
570  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
571 
572  layer->SetAdditionalInfoForObject(activationDesc);
573 
574  // Check that the additional information can be queried from the layer
575  std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
576 
577  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
578  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
579  ARMNN_ASSERT(
580  static_cast<ActivationFunction>(activationDescPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
581  );
582 
583  // Creates extra layers.
584  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
585  auto const weights = graph.AddLayer<ConstantLayer>("weights");
586  auto const bias = graph.AddLayer<ConstantLayer>("bias");
587  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
588 
589  weights->m_LayerOutput = std::make_unique<ScopedTensorHandle>(weightsTensorInfo);
590  weights->m_LayerOutput->Allocate();
591  bias->m_LayerOutput = std::make_unique<ScopedTensorHandle>(biasTensorInfo);
592  bias->m_LayerOutput->Allocate();
593 
594  // Connects up.
595  Connect(input, layer, TensorInfo(inputShape, DataType, inputsQScale));
596  Connect(weights, layer, weightsTensorInfo, 0, 1);
597  Connect(bias, layer, biasTensorInfo, 0, 2);
598  Connect(layer, output, TensorInfo(outputShape, DataType, outputQScale));
599  CreateTensorHandles(graph, factory);
600 
601  // Makes the workload and checks it.
602  auto workload = MakeAndCheckWorkload<Convolution2dWorkload>(*layer, factory, modelOptions);
603 
604  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
605  const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
606  IgnoreUnused(queueDescBlobPtr);
607  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
608  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
609  ARMNN_ASSERT(
610  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
611  );
612 
613  CHECK(queueDescriptor.m_Parameters.m_StrideX == 2);
614  CHECK(queueDescriptor.m_Parameters.m_StrideY == 4);
615  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 3);
616  CHECK(queueDescriptor.m_Parameters.m_PadRight == 3);
617  CHECK(queueDescriptor.m_Parameters.m_PadTop == 1);
618  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 1);
619  CHECK(queueDescriptor.m_Parameters.m_BiasEnabled);
620  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
621 
622  CHECK(queueDescriptor.m_Outputs.size() == 1);
623  CHECK(queueDescriptor.m_Inputs.size() == 3);
624 
625  // Returns so we can do extra, backend-specific tests.
626  return workload;
627 }
628 
629 template <typename Convolution2dWorkload, armnn::DataType DataType>
630 std::unique_ptr<Convolution2dWorkload> CreateConvolution2dWorkloadFastMathTest(armnn::IWorkloadFactory& factory,
631  armnn::Graph& graph,
632  DataLayout dataLayout = DataLayout::NCHW,
633  const ModelOptions& modelOptions = {})
634 {
635  // Creates the layer we're testing.
636  Convolution2dDescriptor layerDesc;
637  layerDesc.m_PadLeft = 0;
638  layerDesc.m_PadRight = 0;
639  layerDesc.m_PadTop = 0;
640  layerDesc.m_PadBottom = 0;
641  layerDesc.m_StrideX = 1;
642  layerDesc.m_StrideY = 1;
643  layerDesc.m_BiasEnabled = true;
644  layerDesc.m_DataLayout = dataLayout;
645 
646  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
647  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
648 
649  Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
650 
651  TensorShape weightShape = TensorShape{ 32, 32, 3, 3 };
652  TensorShape biasShape = TensorShape{ 32 };
653  TensorShape inputShape = TensorShape{ 1, 32, 149, 149 };
654  TensorShape outputShape = TensorShape{ 1, 32, 147, 147 };
655 
656  armnn::TensorInfo weightsTensorInfo(weightShape, DataType, inputsQScale);
657  weightsTensorInfo.SetConstant();
658  armnn::TensorInfo biasTensorInfo(biasShape, DataType, inputsQScale);
659  biasTensorInfo.SetConstant();
660 
661  // Creates extra layers.
662  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
663  auto const weights = graph.AddLayer<ConstantLayer>("weights");
664  auto const bias = graph.AddLayer<ConstantLayer>("bias");
665  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
666 
667  // Connects up.
668  Connect(input, layer, TensorInfo(inputShape, DataType));
669  Connect(weights, layer, weightsTensorInfo, 0, 1);
670  Connect(bias, layer, biasTensorInfo, 0, 2);
671  Connect(layer, output, TensorInfo(outputShape, DataType, outputQScale));
672  CreateTensorHandles(graph, factory);
673 
674  // Makes the workload and checks it.
675  auto workload = MakeAndCheckWorkload<Convolution2dWorkload>(*layer, factory, modelOptions);
676 
677  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
678  CHECK(queueDescriptor.m_Parameters.m_StrideX == 1);
679  CHECK(queueDescriptor.m_Parameters.m_StrideY == 1);
680  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 0);
681  CHECK(queueDescriptor.m_Parameters.m_PadRight == 0);
682  CHECK(queueDescriptor.m_Parameters.m_PadTop == 0);
683  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 0);
684  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
685 
686  CHECK(queueDescriptor.m_Inputs.size() == 3);
687  CHECK(queueDescriptor.m_Outputs.size() == 1);
688 
689  // Returns so we can do extra, backend-specific tests.
690  return workload;
691 }
692 
693 template <typename LstmWorkload>
694 std::unique_ptr<LstmWorkload> CreateLstmWorkloadTest(armnn::IWorkloadFactory& factory, armnn::Graph& graph)
695 {
696  // This parameter setting is for withCifgWithPeepholeNoProjection
697  LstmDescriptor layerDesc;
698  layerDesc.m_ActivationFunc = 4;
699  layerDesc.m_ClippingThresCell = 0.0f;
700  layerDesc.m_ClippingThresProj = 0.0f;
701  layerDesc.m_CifgEnabled = true;
702  layerDesc.m_PeepholeEnabled = true;
703  layerDesc.m_ProjectionEnabled = false;
704 
705  LstmLayer* const layer = graph.AddLayer<LstmLayer>(layerDesc, "layer");
706  unsigned int batchSize = 2;
707  unsigned int inputSize = 2;
708  unsigned int numUnits = 4;
709  unsigned int outputSize = 4;
710 
711  layer->m_BasicParameters.m_InputToForgetWeights = std::make_unique<ScopedTensorHandle>
712  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
713  layer->m_BasicParameters.m_InputToCellWeights = std::make_unique<ScopedTensorHandle>
714  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
715  layer->m_BasicParameters.m_InputToOutputWeights = std::make_unique<ScopedTensorHandle>
716  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
717  layer->m_BasicParameters.m_RecurrentToForgetWeights = std::make_unique<ScopedTensorHandle>
718  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
719  layer->m_BasicParameters.m_RecurrentToCellWeights = std::make_unique<ScopedTensorHandle>
720  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
721  layer->m_BasicParameters.m_RecurrentToOutputWeights = std::make_unique<ScopedTensorHandle>
722  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
723  layer->m_BasicParameters.m_ForgetGateBias = std::make_unique<ScopedTensorHandle>
724  (TensorInfo({ numUnits }, DataType::Float32));
725  layer->m_BasicParameters.m_CellBias = std::make_unique<ScopedTensorHandle>
726  (TensorInfo({ numUnits }, DataType::Float32));
727  layer->m_BasicParameters.m_OutputGateBias = std::make_unique<ScopedTensorHandle>
728  (TensorInfo({ numUnits }, DataType::Float32));
729 
730  layer->m_BasicParameters.m_InputToForgetWeights->Allocate();
731  layer->m_BasicParameters.m_InputToCellWeights->Allocate();
732  layer->m_BasicParameters.m_InputToOutputWeights->Allocate();
734  layer->m_BasicParameters.m_RecurrentToCellWeights->Allocate();
736  layer->m_BasicParameters.m_ForgetGateBias->Allocate();
737  layer->m_BasicParameters.m_CellBias->Allocate();
738  layer->m_BasicParameters.m_OutputGateBias->Allocate();
739 
740 
741  if (layerDesc.m_PeepholeEnabled)
742  {
743  layer->m_PeepholeParameters.m_CellToForgetWeights = std::make_unique<ScopedTensorHandle>
744  (TensorInfo({ numUnits }, DataType::Float32));
745  layer->m_PeepholeParameters.m_CellToOutputWeights = std::make_unique<ScopedTensorHandle>
746  (TensorInfo({ numUnits }, DataType::Float32));
747  layer->m_PeepholeParameters.m_CellToForgetWeights->Allocate();
748  layer->m_PeepholeParameters.m_CellToOutputWeights->Allocate();
749  }
750 
751  // create input and output layers
752  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
753  Layer* const outputStateIn = graph.AddLayer<InputLayer>(1, "outputStateIn");
754  Layer* const cellStateIn = graph.AddLayer<InputLayer>(2, "cellStateIn");
755  Layer* const scratchBuffer = graph.AddLayer<OutputLayer>(0, "scratchBuffer");
756  Layer* const outputStateOut = graph.AddLayer<OutputLayer>(1, "outputStateOut");
757  Layer* const cellStateOut = graph.AddLayer<OutputLayer>(2, "cellStateOut");
758  Layer* const output = graph.AddLayer<OutputLayer>(3, "output");
759 
760  // connect up
761  armnn::TensorInfo lstmTensorInfo1({ batchSize, inputSize }, DataType::Float32);
762  armnn::TensorInfo lstmTensorInfo2({ batchSize, numUnits}, DataType::Float32);
763  armnn::TensorInfo lstmTensorInfo3({ batchSize, outputSize }, DataType::Float32);
764  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * (layerDesc.m_CifgEnabled ? 3 : 4) },
766  Connect(input, layer, lstmTensorInfo1, 0, 0);
767  Connect(cellStateIn, layer, lstmTensorInfo2, 0, 1);
768  Connect(outputStateIn, layer, lstmTensorInfo3, 0, 2);
769  Connect(layer, scratchBuffer, lstmTensorInfoScratchBuff, 0, 0);
770  Connect(layer, outputStateOut, lstmTensorInfo3, 1, 0);
771  Connect(layer, cellStateOut, lstmTensorInfo2, 2, 0);
772  Connect(layer, output, lstmTensorInfo3, 3, 0);
773 
774  CreateTensorHandles(graph, factory);
775 
776  // make the workload and check it
777  auto workload = MakeAndCheckWorkload<LstmWorkload>(*layer, factory);
778  LstmQueueDescriptor queueDescriptor = workload->GetData();
779  CHECK(queueDescriptor.m_Parameters.m_ActivationFunc == 4);
780  CHECK(queueDescriptor.m_Parameters.m_ClippingThresCell == 0.0f);
781  CHECK(queueDescriptor.m_Parameters.m_ClippingThresProj == 0.0f);
782  CHECK(queueDescriptor.m_Inputs.size() == 3);
783  CHECK(queueDescriptor.m_Outputs.size() == 4);
784 
785  CHECK((queueDescriptor.m_InputToForgetWeights->GetTensorInfo() == TensorInfo({ numUnits, inputSize },
787  CHECK((queueDescriptor.m_OutputGateBias->GetTensorInfo() == TensorInfo({ numUnits },
789  CHECK((queueDescriptor.m_CellBias->GetTensorInfo() == TensorInfo({ numUnits }, DataType::Float32)));
790  return workload;
791 }
792 
793 template <typename QuantizedLstmWorkload>
794 std::unique_ptr<QuantizedLstmWorkload> CreateQuantizedLstmWorkloadTest(armnn::IWorkloadFactory& factory,
795  armnn::Graph& graph)
796 {
797  auto layer = graph.AddLayer<QuantizedLstmLayer>("quantizedLstmlayer");
798  unsigned int numBatches = 2;
799  unsigned int inputSize = 2;
800  unsigned int outputSize = 4;
801 
802  // Scale/Offset for input/output, cellState In/Out, weights, bias
803  float inputOutputScale = 0.0078125f;
804  int32_t inputOutputOffset = 128;
805 
806  float cellStateScale = 0.00048828125f;
807  int32_t cellStateOffset = 0;
808 
809  float weightsScale = 0.00408021f;
810  int32_t weightsOffset = 100;
811 
812  float biasScale = 3.1876640625e-05f;
813  int32_t biasOffset = 0;
814 
815  // Weights and bias tensor and quantization info
816  armnn::TensorInfo inputWeightsInfo({outputSize, inputSize},
818  weightsScale,
819  weightsOffset);
820 
821  armnn::TensorInfo recurrentWeightsInfo({outputSize, outputSize},
823  weightsScale,
824  weightsOffset);
825 
826  armnn::TensorInfo biasInfo({outputSize},
828  biasScale,
829  biasOffset);
830 
831  // Weights and bias
832  layer->m_QuantizedLstmParameters.m_InputToInputWeights =
833  std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
834  layer->m_QuantizedLstmParameters.m_InputToForgetWeights =
835  std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
836  layer->m_QuantizedLstmParameters.m_InputToCellWeights =
837  std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
838  layer->m_QuantizedLstmParameters.m_InputToOutputWeights =
839  std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
840 
841  layer->m_QuantizedLstmParameters.m_RecurrentToInputWeights =
842  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
843  layer->m_QuantizedLstmParameters.m_RecurrentToForgetWeights =
844  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
845  layer->m_QuantizedLstmParameters.m_RecurrentToCellWeights =
846  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
847  layer->m_QuantizedLstmParameters.m_RecurrentToOutputWeights =
848  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
849 
850  layer->m_QuantizedLstmParameters.m_InputGateBias = std::make_unique<ScopedTensorHandle>(biasInfo);
851  layer->m_QuantizedLstmParameters.m_ForgetGateBias = std::make_unique<ScopedTensorHandle>(biasInfo);
852  layer->m_QuantizedLstmParameters.m_CellBias = std::make_unique<ScopedTensorHandle>(biasInfo);
853  layer->m_QuantizedLstmParameters.m_OutputGateBias = std::make_unique<ScopedTensorHandle>(biasInfo);
854 
855  // Allocate weights and bias
856  layer->m_QuantizedLstmParameters.m_InputToInputWeights->Allocate();
857  layer->m_QuantizedLstmParameters.m_InputToForgetWeights->Allocate();
858  layer->m_QuantizedLstmParameters.m_InputToCellWeights->Allocate();
859  layer->m_QuantizedLstmParameters.m_InputToOutputWeights->Allocate();
860 
861  layer->m_QuantizedLstmParameters.m_RecurrentToInputWeights->Allocate();
862  layer->m_QuantizedLstmParameters.m_RecurrentToForgetWeights->Allocate();
863  layer->m_QuantizedLstmParameters.m_RecurrentToCellWeights->Allocate();
864  layer->m_QuantizedLstmParameters.m_RecurrentToOutputWeights->Allocate();
865 
866  layer->m_QuantizedLstmParameters.m_InputGateBias->Allocate();
867  layer->m_QuantizedLstmParameters.m_ForgetGateBias->Allocate();
868  layer->m_QuantizedLstmParameters.m_CellBias->Allocate();
869  layer->m_QuantizedLstmParameters.m_OutputGateBias->Allocate();
870 
871  // Create input and output layers
872  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
873  Layer* const cellStateIn = graph.AddLayer<InputLayer>(1, "cellStateIn");
874  Layer* const outputStateIn = graph.AddLayer<InputLayer>(2, "outputStateIn");
875 
876  Layer* const cellStateOut = graph.AddLayer<OutputLayer>(0, "cellStateOut");
877  Layer* const outputStateOut = graph.AddLayer<OutputLayer>(1, "outputStateOut");
878 
879  // Input/output tensor info and quantization info
880  armnn::TensorInfo inputInfo({numBatches , inputSize},
882  inputOutputScale,
883  inputOutputOffset);
884 
885  armnn::TensorInfo cellStateInfo({numBatches , outputSize},
887  cellStateScale,
888  cellStateOffset);
889 
890  armnn::TensorInfo outputStateInfo({numBatches , outputSize},
892  inputOutputScale,
893  inputOutputOffset);
894 
895  // Connect input/output slots
896  Connect(input, layer, inputInfo, 0, 0);
897  Connect(cellStateIn, layer, cellStateInfo, 0, 1);
898  Connect(outputStateIn, layer, outputStateInfo, 0, 2);
899 
900  Connect(layer, cellStateOut, cellStateInfo, 0, 0);
901  Connect(layer, outputStateOut, outputStateInfo, 1, 0);
902 
903  CreateTensorHandles(graph, factory);
904 
905  // Create workload and check layer support
906  auto workload = MakeAndCheckWorkload<QuantizedLstmWorkload>(*layer, factory);
907  QuantizedLstmQueueDescriptor queueDescriptor = workload->GetData();
908 
909  // Validate input/output sizes
910  CHECK(queueDescriptor.m_Inputs.size() == 3);
911  CHECK(queueDescriptor.m_Outputs.size() == 2);
912 
913  // Validate weight tensor info
914  CHECK((queueDescriptor.m_InputToInputWeights->GetTensorInfo() == inputWeightsInfo));
915  CHECK((queueDescriptor.m_InputToForgetWeights->GetTensorInfo() == inputWeightsInfo));
916  CHECK((queueDescriptor.m_InputToCellWeights->GetTensorInfo() == inputWeightsInfo));
917  CHECK((queueDescriptor.m_InputToOutputWeights->GetTensorInfo() == inputWeightsInfo));
918 
919  CHECK((queueDescriptor.m_RecurrentToInputWeights->GetTensorInfo() == recurrentWeightsInfo));
920  CHECK((queueDescriptor.m_RecurrentToForgetWeights->GetTensorInfo() == recurrentWeightsInfo));
921  CHECK((queueDescriptor.m_RecurrentToCellWeights->GetTensorInfo() == recurrentWeightsInfo));
922  CHECK((queueDescriptor.m_RecurrentToOutputWeights->GetTensorInfo() == recurrentWeightsInfo));
923 
924  CHECK((queueDescriptor.m_InputGateBias->GetTensorInfo() == biasInfo));
925  CHECK((queueDescriptor.m_ForgetGateBias->GetTensorInfo() == biasInfo));
926  CHECK((queueDescriptor.m_CellBias->GetTensorInfo() == biasInfo));
927  CHECK((queueDescriptor.m_OutputGateBias->GetTensorInfo() == biasInfo));
928 
929  return workload;
930 }
931 
932 template <typename QLstmWorkload>
933 std::unique_ptr<QLstmWorkload> CreateQLstmWorkloadTest(armnn::IWorkloadFactory& factory,
934  armnn::Graph& graph)
935 {
936  QLstmDescriptor layerDesc;
937  layerDesc.m_CifgEnabled = true;
938  layerDesc.m_PeepholeEnabled = false;
939  layerDesc.m_ProjectionEnabled = false;
940  layerDesc.m_LayerNormEnabled = true;
941 
942  layerDesc.m_CellClip = 0.0f;
943  layerDesc.m_ProjectionClip = 0.0f;
944 
945  layerDesc.m_HiddenStateZeroPoint = 0;
946  layerDesc.m_HiddenStateScale = 0.007f;
947 
948  layerDesc.m_InputIntermediateScale = 0.007059f;
949  layerDesc.m_ForgetIntermediateScale = 0.007812f;
950  layerDesc.m_CellIntermediateScale = 0.007059f;
951  layerDesc.m_OutputIntermediateScale = 0.007812f;
952 
953  QLstmLayer* const layer = graph.AddLayer<QLstmLayer>(layerDesc, "qLstm");
954 
955  unsigned int numBatches = 2;
956  unsigned int inputSize = 4;
957  unsigned int numUnits = 4;
958  unsigned int outputSize = 4;
959 
960  // Scale/Offset quantization info
961  float inputScale = 0.0078125f;
962  int32_t inputOffset = 0;
963 
964  // if (!projectionEnabled) outputScale == hiddenStateScale
965  float outputScale = layerDesc.m_HiddenStateScale;
966  int32_t outputOffset = layerDesc.m_HiddenStateZeroPoint;
967 
968  float cellStateScale = 3.05176e-05f;
969  int32_t cellStateOffset = 0;
970 
971  float weightsScale = 0.00784314f;
972  int32_t weightsOffset = 0;
973 
974  float layerNormScale = 3.05182e-05f;
975  int32_t layerNormOffset = 0;
976 
977  float biasScale = layerNormScale / 1024;
978  int32_t biasOffset = 0;
979 
980  // Weights and bias tensor and quantization info
981  armnn::TensorInfo inputWeightsInfo({outputSize, inputSize},
983  weightsScale,
984  weightsOffset);
985 
986  armnn::TensorInfo recurrentWeightsInfo({outputSize, outputSize},
988  weightsScale,
989  weightsOffset);
990 
991  armnn::TensorInfo biasInfo({outputSize}, armnn::DataType::Signed32, biasScale, biasOffset);
992 
993  armnn::TensorInfo layerNormWeightsInfo({numUnits}, armnn::DataType::QSymmS16, layerNormScale, layerNormOffset);
994 
995  // Create and allocate tensors
996  layer->m_BasicParameters.m_InputToForgetWeights = std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
997  layer->m_BasicParameters.m_InputToCellWeights = std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
998  layer->m_BasicParameters.m_InputToOutputWeights = std::make_unique<ScopedTensorHandle>(inputWeightsInfo);
999 
1001  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
1003  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
1005  std::make_unique<ScopedTensorHandle>(recurrentWeightsInfo);
1006 
1007  layer->m_BasicParameters.m_ForgetGateBias = std::make_unique<ScopedTensorHandle>(biasInfo);
1008  layer->m_BasicParameters.m_CellBias = std::make_unique<ScopedTensorHandle>(biasInfo);
1009  layer->m_BasicParameters.m_OutputGateBias = std::make_unique<ScopedTensorHandle>(biasInfo);
1010 
1012  std::make_unique<ScopedTensorHandle>(layerNormWeightsInfo);
1014  std::make_unique<ScopedTensorHandle>(layerNormWeightsInfo);
1016  std::make_unique<ScopedTensorHandle>(layerNormWeightsInfo);
1017 
1018  layer->m_BasicParameters.m_InputToForgetWeights->Allocate();
1019  layer->m_BasicParameters.m_InputToCellWeights->Allocate();
1020  layer->m_BasicParameters.m_InputToOutputWeights->Allocate();
1021 
1022  layer->m_BasicParameters.m_RecurrentToForgetWeights->Allocate();
1023  layer->m_BasicParameters.m_RecurrentToCellWeights->Allocate();
1024  layer->m_BasicParameters.m_RecurrentToOutputWeights->Allocate();
1025 
1026  layer->m_BasicParameters.m_ForgetGateBias->Allocate();
1027  layer->m_BasicParameters.m_CellBias->Allocate();
1028  layer->m_BasicParameters.m_OutputGateBias->Allocate();
1029 
1031  layer->m_LayerNormParameters.m_CellLayerNormWeights->Allocate();
1033 
1034  // Input and output layers
1035  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1036  Layer* const outputStateIn = graph.AddLayer<InputLayer>(1, "outputStateIn");
1037  Layer* const cellStateIn = graph.AddLayer<InputLayer>(2, "cellStateIn");
1038 
1039  Layer* const outputStateOut = graph.AddLayer<OutputLayer>(0, "outputStateOut");
1040  Layer* const cellStateOut = graph.AddLayer<OutputLayer>(1, "cellStateOut");
1041  Layer* const output = graph.AddLayer<OutputLayer>(2, "output");
1042 
1043  // Input/Output tensor info
1044  armnn::TensorInfo inputInfo({numBatches , inputSize},
1046  inputScale,
1047  inputOffset);
1048 
1049  armnn::TensorInfo cellStateInfo({numBatches , numUnits},
1051  cellStateScale,
1052  cellStateOffset);
1053 
1054  armnn::TensorInfo outputStateInfo({numBatches , outputSize},
1056  outputScale,
1057  outputOffset);
1058 
1059  // Connect layers to slots
1060  Connect(input, layer, inputInfo, 0, 0);
1061  Connect(outputStateIn, layer, outputStateInfo, 0, 1);
1062  Connect(cellStateIn, layer, cellStateInfo, 0, 2);
1063 
1064  Connect(layer, outputStateOut, outputStateInfo, 0, 0);
1065  Connect(layer, cellStateOut, cellStateInfo, 1, 0);
1066  Connect(layer, output, outputStateInfo, 2, 0);
1067 
1068  CreateTensorHandles(graph, factory);
1069 
1070  // Create and check workload
1071  auto workload = MakeAndCheckWorkload<QLstmWorkload>(*layer, factory);
1072  QLstmQueueDescriptor queueDescriptor = workload->GetData();
1073  CHECK(queueDescriptor.m_Parameters.m_CellClip == 0.0f);
1074  CHECK(queueDescriptor.m_Parameters.m_ProjectionClip == 0.0f);
1075  CHECK(queueDescriptor.m_Inputs.size() == 3);
1076  CHECK(queueDescriptor.m_Outputs.size() == 3);
1077 
1078  CHECK((queueDescriptor.m_InputToForgetWeights->GetTensorInfo() == inputWeightsInfo));
1079  CHECK((queueDescriptor.m_InputToCellWeights->GetTensorInfo() == inputWeightsInfo));
1080  CHECK((queueDescriptor.m_InputToOutputWeights->GetTensorInfo() == inputWeightsInfo));
1081 
1082  CHECK((queueDescriptor.m_RecurrentToForgetWeights->GetTensorInfo() == recurrentWeightsInfo));
1083  CHECK((queueDescriptor.m_RecurrentToCellWeights->GetTensorInfo() == recurrentWeightsInfo));
1084  CHECK((queueDescriptor.m_RecurrentToOutputWeights->GetTensorInfo() == recurrentWeightsInfo));
1085 
1086  CHECK((queueDescriptor.m_ForgetGateBias->GetTensorInfo() == biasInfo));
1087  CHECK((queueDescriptor.m_CellBias->GetTensorInfo() == biasInfo));
1088  CHECK((queueDescriptor.m_OutputGateBias->GetTensorInfo() == biasInfo));
1089 
1090  return workload;
1091 }
1092 
1093 template<typename Convolution2dWorkload, armnn::DataType DataType>
1094 std::unique_ptr<Convolution2dWorkload> CreateDirectConvolution2dWorkloadTest(armnn::IWorkloadFactory& factory,
1095  armnn::Graph& graph)
1096 {
1097  // Creates the layer we're testing.
1098  Convolution2dDescriptor layerDesc;
1099  layerDesc.m_PadLeft = 1;
1100  layerDesc.m_PadRight = 1;
1101  layerDesc.m_PadTop = 1;
1102  layerDesc.m_PadBottom = 1;
1103  layerDesc.m_StrideX = 1;
1104  layerDesc.m_StrideY = 1;
1105  layerDesc.m_BiasEnabled = true;
1106 
1107  Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
1108 
1109  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
1110  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
1111 
1112  TensorShape biasShape = TensorShape{ 2 };
1113  TensorShape weightShape = TensorShape{ 2, 3, 3, 3 };
1114  armnn::TensorInfo weightsTensorInfo(weightShape, DataType, inputsQScale);
1115  weightsTensorInfo.SetConstant();
1116  armnn::TensorInfo biasTensorInfo(biasShape, GetBiasDataType(DataType), inputsQScale);
1117  biasTensorInfo.SetConstant();
1118 
1119  // Creates extra layers.
1120  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1121  auto const weights = graph.AddLayer<ConstantLayer>("weights");
1122  auto const bias = graph.AddLayer<ConstantLayer>("bias");
1123  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1124 
1125  weights->m_LayerOutput = std::make_unique<ScopedTensorHandle>(weightsTensorInfo);
1126  weights->m_LayerOutput->Allocate();
1127  bias->m_LayerOutput = std::make_unique<ScopedTensorHandle>(biasTensorInfo);
1128  bias->m_LayerOutput->Allocate();
1129 
1130  // Connects up.
1131  Connect(input, layer, TensorInfo({2, 3, 6, 6}, DataType, inputsQScale));
1132  Connect(weights, layer, weightsTensorInfo, 0, 1);
1133  Connect(bias, layer, biasTensorInfo, 0, 2);
1134  Connect(layer, output, TensorInfo({2, 2, 6, 6}, DataType, outputQScale));
1135  CreateTensorHandles(graph, factory);
1136 
1137  // Makes the workload and checks it.
1138  auto workload = MakeAndCheckWorkload<Convolution2dWorkload>(*layer, factory);
1139 
1140  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
1141  CHECK(queueDescriptor.m_Parameters.m_StrideX == 1);
1142  CHECK(queueDescriptor.m_Parameters.m_StrideY == 1);
1143  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 1);
1144  CHECK(queueDescriptor.m_Parameters.m_PadRight == 1);
1145  CHECK(queueDescriptor.m_Parameters.m_PadTop == 1);
1146  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 1);
1147  CHECK(queueDescriptor.m_Parameters.m_BiasEnabled == true);
1148 
1149  CHECK(queueDescriptor.m_Inputs.size() == 3);
1150  CHECK(queueDescriptor.m_Outputs.size() == 1);
1151 
1152  // Returns so we can do extra, backend-specific tests.
1153  return workload;
1154 }
1155 
1156 template <typename DepthwiseConvolution2dFloat32Workload, armnn::DataType DataType>
1157 std::unique_ptr<DepthwiseConvolution2dFloat32Workload> CreateDepthwiseConvolution2dWorkloadTest(
1158  armnn::IWorkloadFactory& factory, armnn::Graph& graph, DataLayout dataLayout = DataLayout::NCHW)
1159 {
1160  // Creates the layer we're testing.
1162  layerDesc.m_PadLeft = 1;
1163  layerDesc.m_PadRight = 2;
1164  layerDesc.m_PadTop = 1;
1165  layerDesc.m_PadBottom = 2;
1166  layerDesc.m_StrideX = 1;
1167  layerDesc.m_StrideY = 1;
1168  layerDesc.m_BiasEnabled = false;
1169  layerDesc.m_DataLayout = dataLayout;
1170 
1171  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
1172  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
1173 
1174  TensorShape weightShape({1, 4, 4, 2});
1175  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
1176  TensorShape{ 2, 2, 5, 5 } : TensorShape{ 2, 5, 5, 2 };
1177  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
1178  TensorShape{ 2, 2, 5, 5 } : TensorShape{ 2, 5, 5, 2 };
1179 
1180  DepthwiseConvolution2dLayer* const layer = graph.AddLayer<DepthwiseConvolution2dLayer>(layerDesc, "layer");
1181 
1182 
1183  // Creates extra layers.
1184  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1185  Layer* const weights = graph.AddLayer<ConstantLayer>("weights");
1186  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1187 
1188  // Connects up.
1189  Connect(input, layer, TensorInfo(inputShape, DataType, inputsQScale));
1190  Connect(weights, layer, TensorInfo(weightShape, DataType, inputsQScale, 0.0f, true), 0, 1);
1191  Connect(layer, output, TensorInfo(outputShape, DataType, outputQScale));
1192  CreateTensorHandles(graph, factory);
1193 
1194  // Makes the workload and checks it.
1195  auto workload = MakeAndCheckWorkload<DepthwiseConvolution2dFloat32Workload>(*layer, factory);
1196 
1197  DepthwiseConvolution2dQueueDescriptor queueDescriptor = workload->GetData();
1198  CHECK(queueDescriptor.m_Parameters.m_StrideX == 1);
1199  CHECK(queueDescriptor.m_Parameters.m_StrideY == 1);
1200  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 1);
1201  CHECK(queueDescriptor.m_Parameters.m_PadRight == 2);
1202  CHECK(queueDescriptor.m_Parameters.m_PadTop == 1);
1203  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 2);
1204  CHECK(queueDescriptor.m_Parameters.m_BiasEnabled == false);
1205  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
1206 
1207  CHECK(queueDescriptor.m_Inputs.size() == 2);
1208  CHECK(queueDescriptor.m_Outputs.size() == 1);
1209 
1210  // Returns so we can do extra, backend-specific tests.
1211  return workload;
1212 }
1213 
1214 template <typename FullyConnectedWorkload, armnn::DataType DataType>
1215 std::unique_ptr<FullyConnectedWorkload> CreateFullyConnectedWorkloadTest(armnn::IWorkloadFactory& factory,
1216  armnn::Graph& graph)
1217 {
1218  // Creates the layer we're testing.
1219  FullyConnectedDescriptor layerDesc;
1220  layerDesc.m_BiasEnabled = false;
1221  layerDesc.m_TransposeWeightMatrix = true;
1222 
1223  FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");
1224 
1225  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
1226  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
1227 
1228  armnn::TensorInfo weightsTensorInfo({7, 20}, DataType, inputsQScale);
1229  weightsTensorInfo.SetConstant();
1230 
1231  // Creates extra layers.
1232  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1233  auto const weights = graph.AddLayer<ConstantLayer>("weights");
1234  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1235 
1236  weights->m_LayerOutput = std::make_unique<ScopedTensorHandle>(weightsTensorInfo);
1237  weights->m_LayerOutput->Allocate();
1238 
1239  // Connects up.
1240  Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType, inputsQScale), 0, 0);
1241  Connect(weights, layer, weightsTensorInfo, 0, 1);
1242  Connect(layer, output, TensorInfo({3, 7}, DataType, outputQScale));
1243  CreateTensorHandles(graph, factory);
1244 
1245  // Makes the workload and checks it.
1246  auto workload = MakeAndCheckWorkload<FullyConnectedWorkload>(*layer, factory);
1247 
1248  FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
1249  CHECK(queueDescriptor.m_Parameters.m_TransposeWeightMatrix == true);
1250 
1251  CHECK(queueDescriptor.m_Inputs.size() == 2);
1252  CHECK(queueDescriptor.m_Outputs.size() == 1);
1253 
1254  // Returns so we can do extra, backend-specific tests.
1255  return workload;
1256 }
1257 
1258 template <typename FullyConnectedWorkload, armnn::DataType DataType>
1259 std::unique_ptr<FullyConnectedWorkload> CreateFullyConnectedWithBlobWorkloadTest
1260  (armnn::IWorkloadFactory& factory,
1261  armnn::Graph& graph)
1262 {
1263  // Creates the layer we're testing.
1264  FullyConnectedDescriptor layerDesc;
1265  layerDesc.m_BiasEnabled = true;
1266  layerDesc.m_TransposeWeightMatrix = true;
1267 
1268  FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");
1269 
1270  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
1271  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
1272 
1273  armnn::TensorInfo weightsTensorInfo({7, 20}, DataType, inputsQScale);
1274  armnn::TensorInfo biasesTensorInfo({7}, GetBiasDataType(DataType), inputsQScale);
1275  weightsTensorInfo.SetConstant();
1276  biasesTensorInfo.SetConstant();
1277 
1278  auto activationDesc = std::make_shared<ActivationDescriptor>();
1279  activationDesc->m_A = 10.0f;
1280  activationDesc->m_B = 5.0f;
1281  activationDesc->m_Function = armnn::ActivationFunction::BoundedReLu;
1282 
1283  layer->SetAdditionalInfoForObject(activationDesc);
1284 
1285  // Check that the additional information can be queried from the layer
1286  std::shared_ptr<ActivationDescriptor> activationDescPtr = layer->GetAdditionalInformation<ActivationDescriptor>();
1287  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_A) == 10.0f);
1288  ARMNN_ASSERT(static_cast<float>(activationDescPtr->m_B) == 5.0f);
1289  ARMNN_ASSERT(static_cast<ActivationFunction>(activationDescPtr->m_Function) ==
1291 
1292  // Creates extra layers.
1293  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1294  auto const weights = graph.AddLayer<ConstantLayer>("weights");
1295  auto const biases = graph.AddLayer<ConstantLayer>("biases");
1296  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1297 
1298  weights->m_LayerOutput = std::make_unique<ScopedTensorHandle>(weightsTensorInfo);
1299  weights->m_LayerOutput->Allocate();
1300  biases->m_LayerOutput = std::make_unique<ScopedTensorHandle>(biasesTensorInfo);
1301  biases->m_LayerOutput->Allocate();
1302 
1303  // Connects up.
1304  Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType, inputsQScale), 0, 0);
1305  Connect(weights, layer, weightsTensorInfo, 0, 1);
1306  Connect(biases, layer, biasesTensorInfo, 0, 2);
1307  Connect(layer, output, TensorInfo({3, 7}, DataType, outputQScale));
1308  CreateTensorHandles(graph, factory);
1309 
1310  // Makes the workload and checks it.
1311  auto workload = MakeAndCheckWorkload<FullyConnectedWorkload>(*layer, factory);
1312 
1313  FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
1314 
1315  const ActivationDescriptor* queueDescBlobPtr = queueDescriptor.GetAdditionalInformation<ActivationDescriptor>();
1316  IgnoreUnused(queueDescBlobPtr);
1317 
1318  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_A) == 10.0f);
1319  ARMNN_ASSERT(static_cast<float>(queueDescBlobPtr->m_B) == 5.0f);
1320  ARMNN_ASSERT(
1321  static_cast<ActivationFunction>(queueDescBlobPtr->m_Function) == armnn::ActivationFunction::BoundedReLu
1322  );
1323 
1324  CHECK(queueDescriptor.m_Parameters.m_BiasEnabled == true);
1325  CHECK(queueDescriptor.m_Parameters.m_TransposeWeightMatrix == true);
1326  CHECK(queueDescriptor.m_Inputs.size() == 3);
1327  CHECK(queueDescriptor.m_Outputs.size() == 1);
1328 
1329  // Returns so we can do extra, backend-specific tests.
1330  return workload;
1331 }
1332 
1333 template <typename FullyConnectedWorkload, armnn::DataType DataType>
1334 std::unique_ptr<FullyConnectedWorkload> CreateFullyConnectedWorkloadWeightsBiasesAsInputsTest
1335  (armnn::IWorkloadFactory& factory,
1336  armnn::Graph& graph)
1337 {
1338  // Creates the layer we're testing.
1339  FullyConnectedDescriptor layerDesc;
1340  layerDesc.m_BiasEnabled = true;
1341  layerDesc.m_TransposeWeightMatrix = true;
1342  layerDesc.m_ConstantWeights = false;
1343 
1344  FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");
1345 
1346  float inputsQScale = DataType == armnn::DataType::QAsymmU8 ? 1.0f : 0.0;
1347  float outputQScale = DataType == armnn::DataType::QAsymmU8 ? 2.0f : 0.0;
1348 
1349  // Creates extra layers with weights and biases as input layers.
1350  Layer* const input = graph.AddLayer<InputLayer>(1, "input");
1351  Layer* const weights = graph.AddLayer<InputLayer>(2, "weights");
1352  Layer* const biases = graph.AddLayer<InputLayer>(3, "biases");
1353  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1354 
1355  // Connects up.
1356  Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType, inputsQScale), 0, 0);
1357  Connect(weights, layer, TensorInfo({7, 20}, DataType, inputsQScale), 0, 1);
1358  Connect(biases, layer, TensorInfo({7}, GetBiasDataType(DataType), inputsQScale), 0, 2);
1359  Connect(layer, output, TensorInfo({3, 7}, DataType, outputQScale));
1360  CreateTensorHandles(graph, factory);
1361 
1362  // Makes the workload and checks it.
1363  auto workload = MakeAndCheckWorkload<FullyConnectedWorkload>(*layer, factory);
1364 
1365  FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
1366 
1367  CHECK(queueDescriptor.m_Parameters.m_BiasEnabled == true);
1368  CHECK(queueDescriptor.m_Parameters.m_TransposeWeightMatrix == true);
1369  CHECK(queueDescriptor.m_Parameters.m_ConstantWeights == false);
1370  CHECK(queueDescriptor.m_Inputs.size() == 3);
1371  CHECK(queueDescriptor.m_Outputs.size() == 1);
1372 
1373  // Returns so we can do extra, backend-specific tests.
1374  return workload;
1375 }
1376 
1377 
1378 template <typename NormalizationWorkload, armnn::DataType DataType>
1379 std::unique_ptr<NormalizationWorkload> CreateNormalizationWorkloadTest(armnn::IWorkloadFactory& factory,
1380  armnn::Graph& graph,
1381  DataLayout dataLayout = DataLayout::NCHW)
1382 {
1383  // Creates the layer we're testing.
1384  NormalizationDescriptor layerDesc;
1387  layerDesc.m_NormSize = 3;
1388  layerDesc.m_Alpha = 0.5f;
1389  layerDesc.m_Beta = -1.0f;
1390  layerDesc.m_K = 0.2f;
1391  layerDesc.m_DataLayout = dataLayout;
1392 
1393  NormalizationLayer* layer = graph.AddLayer<NormalizationLayer>(layerDesc, "layer");
1394 
1395  // Creates extra layers.
1396  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1397  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1398 
1399  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
1400  TensorShape{ 3, 5, 5, 1 } : TensorShape{ 3, 1, 5, 5 };
1401  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
1402  TensorShape{ 3, 5, 5, 1 } : TensorShape{ 3, 1, 5, 5 };
1403 
1404  // Connects up.
1405  armnn::TensorInfo inputTensorInfo(inputShape, DataType);
1406  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
1407  Connect(input, layer, inputTensorInfo);
1408  Connect(layer, output, outputTensorInfo);
1409  CreateTensorHandles(graph, factory);
1410 
1411  // Makes the workload and checks it.
1412  auto workload = MakeAndCheckWorkload<NormalizationWorkload>(*layer, factory);
1413 
1414  NormalizationQueueDescriptor queueDescriptor = workload->GetData();
1417  CHECK(queueDescriptor.m_Parameters.m_NormSize == 3);
1418  CHECK(queueDescriptor.m_Parameters.m_Alpha == 0.5f);
1419  CHECK(queueDescriptor.m_Parameters.m_Beta == -1.0f);
1420  CHECK(queueDescriptor.m_Parameters.m_K == 0.2f);
1421  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
1422 
1423  CHECK(queueDescriptor.m_Inputs.size() == 1);
1424  CHECK(queueDescriptor.m_Outputs.size() == 1);
1425 
1426  // Returns so we can do extra, backend-specific tests.
1427  return workload;
1428 }
1429 
1430 template <typename Pooling2dWorkload, armnn::DataType DataType>
1431 std::unique_ptr<Pooling2dWorkload> CreatePooling2dWorkloadTest(armnn::IWorkloadFactory& factory,
1432  armnn::Graph& graph,
1433  DataLayout dataLayout = DataLayout::NCHW)
1434 {
1435  // Creates the layer we're testing.
1436  Pooling2dDescriptor layerDesc;
1438  layerDesc.m_PoolWidth = 3;
1439  layerDesc.m_PoolHeight = 3;
1440  layerDesc.m_PadLeft = 2;
1441  layerDesc.m_PadRight = 2;
1442  layerDesc.m_PadTop = 1;
1443  layerDesc.m_PadBottom = 1;
1444  layerDesc.m_StrideX = 2;
1445  layerDesc.m_StrideY = 3;
1447  layerDesc.m_DataLayout = dataLayout;
1448 
1449  Pooling2dLayer* const layer = graph.AddLayer<Pooling2dLayer>(layerDesc, "layer");
1450 
1451  // Create extra layers
1452  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1453  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1454 
1455  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 5, 5} : TensorShape{3, 5, 5, 2};
1456  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 2, 4} : TensorShape{3, 2, 4, 2};
1457 
1458  // Connect up
1459  Connect(input, layer, TensorInfo(inputShape, DataType));
1460  Connect(layer, output, TensorInfo(outputShape, DataType));
1461  CreateTensorHandles(graph, factory);
1462 
1463  // Make the workload and checks it
1464  auto workload = MakeAndCheckWorkload<Pooling2dWorkload>(*layer, factory);
1465 
1466  Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
1467  CHECK((queueDescriptor.m_Parameters.m_PoolType == PoolingAlgorithm::Average));
1469  CHECK(queueDescriptor.m_Parameters.m_PoolWidth == 3);
1470  CHECK(queueDescriptor.m_Parameters.m_PoolHeight == 3);
1471  CHECK(queueDescriptor.m_Parameters.m_StrideX == 2);
1472  CHECK(queueDescriptor.m_Parameters.m_StrideY == 3);
1473  CHECK(queueDescriptor.m_Parameters.m_PadLeft == 2);
1474  CHECK(queueDescriptor.m_Parameters.m_PadRight == 2);
1475  CHECK(queueDescriptor.m_Parameters.m_PadTop == 1);
1476  CHECK(queueDescriptor.m_Parameters.m_PadBottom == 1);
1477  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
1478 
1479  CHECK(queueDescriptor.m_Inputs.size() == 1);
1480  CHECK(queueDescriptor.m_Outputs.size() == 1);
1481 
1482  // Return so we can do extra, backend-specific tests
1483  return workload;
1484 }
1485 
1486 template <typename SoftmaxWorkload, armnn::DataType DataType>
1487 std::unique_ptr<SoftmaxWorkload> CreateSoftmaxWorkloadTest(armnn::IWorkloadFactory& factory,
1488  armnn::Graph& graph)
1489 {
1490  // Create the layer we're testing.
1491  SoftmaxDescriptor softmaxDescriptor;
1492  // Set Axis to -1 if CL or Neon until further Axes are supported.
1494  {
1495  softmaxDescriptor.m_Axis = -1;
1496  }
1497 
1498  Layer* const layer = graph.AddLayer<SoftmaxLayer>(softmaxDescriptor, "layer");
1499  // Create extra layers.
1500  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1501  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1502 
1503  // Connect up
1504  armnn::TensorInfo tensorInfo({4, 1}, DataType);
1506  {
1507  tensorInfo.SetQuantizationOffset(0);
1508  tensorInfo.SetQuantizationScale(1.f / 256);
1509  }
1510  else if (DataType == armnn::DataType::QAsymmS8)
1511  {
1512  tensorInfo.SetQuantizationOffset(-128);
1513  tensorInfo.SetQuantizationScale(1.f / 256);
1514  }
1515 
1516  Connect(input, layer, tensorInfo);
1517  Connect(layer, output, tensorInfo);
1518  CreateTensorHandles(graph, factory);
1519 
1520  // Make the workload and checks it.
1521  auto workload = MakeAndCheckWorkload<SoftmaxWorkload>(*layer, factory);
1522 
1523  SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
1524  CHECK(queueDescriptor.m_Inputs.size() == 1);
1525  CHECK(queueDescriptor.m_Outputs.size() == 1);
1526 
1527  // Return so we can do extra, backend-specific tests.
1528  return workload;
1529 }
1530 
1531 template<typename SplitterWorkload, armnn::DataType DataType>
1532 std::unique_ptr<SplitterWorkload>
1533  CreateSplitterWorkloadTest(armnn::IWorkloadFactory& factory, armnn::Graph& graph)
1534 {
1535  // Create the layer we're testing.
1536  // NOTE: need three dimensions channels, height/y, width/x because the Compute
1537  // library restricts subtensors to have the same x and y dimensions as
1538  // their parent tensors, and therefore the origin on the x and y dimension
1539  // has to be zero for any view. So we need a third dimension to split...
1540  // NOTE: arguments are: number of views, number of dimensions.
1541  ViewsDescriptor layerDesc(3, 3);
1542  // NOTE: arguments are: view, dimension, value.
1543  layerDesc.SetViewOriginCoord(0, 0, 0);
1544  layerDesc.SetViewOriginCoord(1, 0, 1);
1545  layerDesc.SetViewOriginCoord(2, 0, 3);
1546 
1547  Layer* const layer = graph.AddLayer<SplitterLayer>(layerDesc, "layer");
1548 
1549  // Adds extra layers.
1550  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1551  Layer* const output0 = graph.AddLayer<OutputLayer>(0, "output0");
1552  Layer* const output1 = graph.AddLayer<OutputLayer>(1, "output1");
1553  Layer* const output2 = graph.AddLayer<OutputLayer>(2, "output2");
1554 
1555  // Connects up.
1556  armnn::TensorInfo tensorInfo({5, 7, 7}, DataType);
1557  Connect(input, layer, tensorInfo);
1558 
1559  armnn::TensorInfo output0Info({1, 7, 7}, DataType);
1560  armnn::TensorInfo output1Info({2, 7, 7}, DataType);
1561  armnn::TensorInfo output2Info({2, 7, 7}, DataType);
1562 
1563  Connect(layer, output0, output0Info, 0, 0);
1564  Connect(layer, output1, output1Info, 1, 0);
1565  Connect(layer, output2, output2Info, 2, 0);
1566 
1567  CreateTensorHandles(graph, factory);
1568 
1569  // Makes the workload and checks it.
1570  auto workload = MakeAndCheckWorkload<SplitterWorkload>(*layer, factory);
1571 
1572  SplitterQueueDescriptor queueDescriptor = workload->GetData();
1573  CHECK(queueDescriptor.m_Inputs.size() == 1);
1574  CHECK(queueDescriptor.m_Outputs.size() == 3);
1575  CHECK(queueDescriptor.m_ViewOrigins.size() == 3);
1576 
1577  CHECK(queueDescriptor.m_ViewOrigins[0].m_Origin[0] == 0);
1578  CHECK(queueDescriptor.m_ViewOrigins[1].m_Origin[0] == 1);
1579  CHECK(queueDescriptor.m_ViewOrigins[2].m_Origin[0] == 3);
1580  CHECK(queueDescriptor.m_ViewOrigins[0].m_Origin[1] == 0);
1581  CHECK(queueDescriptor.m_ViewOrigins[1].m_Origin[1] == 0);
1582  CHECK(queueDescriptor.m_ViewOrigins[2].m_Origin[1] == 0);
1583  CHECK(queueDescriptor.m_ViewOrigins[0].m_Origin[2] == 0);
1584  CHECK(queueDescriptor.m_ViewOrigins[1].m_Origin[2] == 0);
1585  CHECK(queueDescriptor.m_ViewOrigins[2].m_Origin[2] == 0);
1586 
1587  // Returns so we can do extra, backend-specific tests.
1588  return workload;
1589 }
1590 
1591 /// This function constructs a graph with both a splitter and a concat, and returns a pair of the workloads.
1592 template<typename SplitterWorkload, typename ConcatWorkload, armnn::DataType DataType>
1593 std::pair<std::unique_ptr<SplitterWorkload>, std::unique_ptr<ConcatWorkload>>
1594  CreateSplitterConcatWorkloadTest(armnn::IWorkloadFactory &factory, armnn::Graph &graph)
1595 {
1596  armnn::TensorInfo inputTensorInfo({ 1, 2, 100, 10 }, DataType);
1597 
1598  armnn::TensorInfo splitTensorInfo1({ 1, 1, 100, 10 }, DataType);
1599  armnn::TensorInfo splitTensorInfo2({ 1, 1, 100, 10 }, DataType);
1600 
1601  //Constructs the graph.
1602  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1603 
1604  armnn::ViewsDescriptor splitterViews(2);
1605  splitterViews.SetViewOriginCoord(0, 0, 0);
1606  splitterViews.SetViewOriginCoord(0, 1, 0);
1607  splitterViews.SetViewOriginCoord(0, 2, 0);
1608  splitterViews.SetViewOriginCoord(0, 3, 0);
1609 
1610  splitterViews.SetViewOriginCoord(1, 0, 0);
1611  splitterViews.SetViewOriginCoord(1, 1, 1);
1612  splitterViews.SetViewOriginCoord(1, 2, 0);
1613  splitterViews.SetViewOriginCoord(1, 3, 0);
1614 
1615  // create splitter layer
1616  Layer* const splitter = graph.AddLayer<SplitterLayer>(splitterViews, "splitter");
1617  CHECK(splitter);
1618 
1619  armnn::OriginsDescriptor concatViews(2);
1620  concatViews.SetViewOriginCoord(0, 0, 0);
1621  concatViews.SetViewOriginCoord(0, 1, 1);
1622  concatViews.SetViewOriginCoord(0, 2, 0);
1623  concatViews.SetViewOriginCoord(0, 3, 0);
1624 
1625  concatViews.SetViewOriginCoord(1, 0, 0);
1626  concatViews.SetViewOriginCoord(1, 1, 0);
1627  concatViews.SetViewOriginCoord(1, 2, 0);
1628  concatViews.SetViewOriginCoord(1, 3, 0);
1629 
1630  // create concat layer
1631  Layer* const concat = graph.AddLayer<ConcatLayer>(concatViews, "concat");
1632  CHECK(concat);
1633 
1634  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1635 
1636  // Adds connections.
1637  // connect input to splitter
1638  Connect(input, splitter, inputTensorInfo, 0, 0);
1639  // connect splitter[0] to concat[1]
1640  Connect(splitter, concat, splitTensorInfo1, 0, 1); // The splitter & concat are connected up.
1641  // connect splitter[1] to concat[0]
1642  Connect(splitter, concat, splitTensorInfo2, 1, 0); // So that the outputs are flipped round.
1643  // connect concat to output
1644  Connect(concat, output, inputTensorInfo, 0, 0);
1645 
1646  // created tensor handles
1647  CreateTensorHandles(graph, factory);
1648 
1649  // created splitter workload
1650  auto workloadSplitter = MakeAndCheckWorkload<SplitterWorkload>(*splitter, factory);
1651  CHECK(workloadSplitter);
1652  // created concat workload
1653  auto workloadConcat = MakeAndCheckWorkload<ConcatWorkload>(*concat, factory);
1654  CHECK(workloadConcat);
1655 
1656  return {std::move(workloadSplitter), std::move(workloadConcat)};
1657 }
1658 
1659 
1660 /// This function constructs a graph with a splitter with two outputs. Each of the outputs is then
1661 /// connected to two different activation layers
1662 template<typename SplitterWorkload, typename ActivationWorkload, armnn::DataType DataType>
1663 void CreateSplitterMultipleInputsOneOutputWorkloadTest(armnn::IWorkloadFactory& factory, armnn::Graph& graph,
1664  std::unique_ptr<SplitterWorkload>& wlSplitter,
1665  std::unique_ptr<ActivationWorkload>& wlActiv0_0,
1666  std::unique_ptr<ActivationWorkload>& wlActiv0_1,
1667  std::unique_ptr<ActivationWorkload>& wlActiv1_0,
1668  std::unique_ptr<ActivationWorkload>& wlActiv1_1)
1669 {
1670  armnn::TensorInfo inputTensorInfo ({ 1, 3, 100, 50 }, DataType);
1671  armnn::TensorInfo splitTensorInfo1({ 1, 1, 100, 50 }, DataType);
1672  armnn::TensorInfo splitTensorInfo2({ 1, 2, 100, 50 }, DataType);
1673 
1674  //Constructs the graph.
1675  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1676 
1677  armnn::ViewsDescriptor splitterViews(2);
1678 
1679  splitterViews.SetViewOriginCoord(0, 0, 0);
1680  splitterViews.SetViewOriginCoord(0, 1, 0);
1681  splitterViews.SetViewOriginCoord(0, 2, 0);
1682  splitterViews.SetViewOriginCoord(0, 3, 0);
1683 
1684  splitterViews.SetViewOriginCoord(1, 0, 0);
1685  splitterViews.SetViewOriginCoord(1, 1, 1);
1686  splitterViews.SetViewOriginCoord(1, 2, 0);
1687  splitterViews.SetViewOriginCoord(1, 3, 0);
1688 
1689  Layer* const splitter = graph.AddLayer<SplitterLayer>(splitterViews, "splitter");
1690 
1691  armnn::ActivationDescriptor activationDesc;
1692 
1693  Layer* const activ0_0 = graph.AddLayer<ActivationLayer>(activationDesc, "activ0_0");
1694  Layer* const activ0_1 = graph.AddLayer<ActivationLayer>(activationDesc, "activ0_1");
1695  Layer* const activ1_0 = graph.AddLayer<ActivationLayer>(activationDesc, "activ1_0");
1696  Layer* const activ1_1 = graph.AddLayer<ActivationLayer>(activationDesc, "activ1_1");
1697 
1698  Layer* const output1 = graph.AddLayer<OutputLayer>(1, "output1");
1699  Layer* const output2 = graph.AddLayer<OutputLayer>(2, "output2");
1700  Layer* const output3 = graph.AddLayer<OutputLayer>(3, "output3");
1701  Layer* const output4 = graph.AddLayer<OutputLayer>(4, "output4");
1702 
1703  // Adds connections.
1704  Connect(input, splitter, inputTensorInfo, 0, 0);
1705  Connect(splitter, activ0_0, splitTensorInfo1, 0, 0);
1706  Connect(splitter, activ0_1, splitTensorInfo1, 0, 0);
1707 
1708  Connect(splitter, activ1_0, splitTensorInfo2, 1, 0);
1709  Connect(splitter, activ1_1, splitTensorInfo2, 1, 0);
1710 
1711  Connect(activ0_0, output1, splitTensorInfo1, 0, 0);
1712  Connect(activ0_1, output2, splitTensorInfo1, 0, 0);
1713  Connect(activ1_0, output3, splitTensorInfo2, 0, 0);
1714  Connect(activ1_1, output4, splitTensorInfo2, 0, 0);
1715 
1716  CreateTensorHandles(graph, factory);
1717 
1718  auto workloadSplitter = MakeAndCheckWorkload<SplitterWorkload>(*splitter, factory);
1719  auto workloadActiv0_0 = MakeAndCheckWorkload<ActivationWorkload>(*activ0_0, factory);
1720  auto workloadActiv0_1 = MakeAndCheckWorkload<ActivationWorkload>(*activ0_1, factory);
1721  auto workloadActiv1_0 = MakeAndCheckWorkload<ActivationWorkload>(*activ1_0, factory);
1722  auto workloadActiv1_1 = MakeAndCheckWorkload<ActivationWorkload>(*activ1_1, factory);
1723 
1724  wlSplitter = std::move(workloadSplitter);
1725  wlActiv0_0 = std::move(workloadActiv0_0);
1726  wlActiv0_1 = std::move(workloadActiv0_1);
1727  wlActiv1_0 = std::move(workloadActiv1_0);
1728  wlActiv1_1 = std::move(workloadActiv1_1);
1729 }
1730 
1731 template <typename ResizeWorkload, armnn::DataType DataType>
1732 std::unique_ptr<ResizeWorkload> CreateResizeBilinearWorkloadTest(armnn::IWorkloadFactory& factory,
1733  armnn::Graph& graph,
1734  DataLayout dataLayout = DataLayout::NCHW)
1735 {
1736  TensorShape inputShape;
1737  TensorShape outputShape;
1738 
1739  switch (dataLayout) {
1740  case DataLayout::NHWC:
1741  inputShape = { 2, 4, 4, 3 };
1742  outputShape = { 2, 2, 2, 3 };
1743  break;
1744  case DataLayout::NCHW:
1745  default:
1746  inputShape = { 2, 3, 4, 4 };
1747  outputShape = { 2, 3, 2, 2 };
1748  }
1749 
1750  // Creates the layer we're testing.
1751  ResizeDescriptor resizeDesc;
1752  armnnUtils::DataLayoutIndexed dimensionIndices = dataLayout;
1753  resizeDesc.m_Method = ResizeMethod::Bilinear;
1754  resizeDesc.m_TargetWidth = outputShape[dimensionIndices.GetWidthIndex()];
1755  resizeDesc.m_TargetHeight = outputShape[dimensionIndices.GetHeightIndex()];
1756  resizeDesc.m_DataLayout = dataLayout;
1757  Layer* const layer = graph.AddLayer<ResizeLayer>(resizeDesc, "resize");
1758 
1759  // Creates extra layers.
1760  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1761  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1762 
1763  // Connects up.
1764  armnn::TensorInfo inputTensorInfo(inputShape, DataType);
1765  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
1766  Connect(input, layer, inputTensorInfo);
1767  Connect(layer, output, outputTensorInfo);
1768  CreateTensorHandles(graph, factory);
1769 
1770  // Makes the workload and checks it.
1771  auto workload = MakeAndCheckWorkload<ResizeWorkload>(*layer, factory);
1772 
1773  auto queueDescriptor = workload->GetData();
1774  CHECK(queueDescriptor.m_Inputs.size() == 1);
1775  CHECK(queueDescriptor.m_Outputs.size() == 1);
1776  CHECK(queueDescriptor.m_Parameters.m_DataLayout == dataLayout);
1777 
1778  // Returns so we can do extra, backend-specific tests.
1779  return workload;
1780 }
1781 
1782 template <typename BatchToSpaceNdWorkload, armnn::DataType DataType>
1783 std::unique_ptr<BatchToSpaceNdWorkload> CreateBatchToSpaceNdWorkloadTest(armnn::IWorkloadFactory& factory,
1784  armnn::Graph& graph)
1785 {
1787  Layer* const layer = graph.AddLayer<BatchToSpaceNdLayer>(desc, "batchToSpace");
1788 
1789  // Creates extra layers.
1790  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1791  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1792 
1793  // Connects up.
1794  armnn::TensorInfo tensorInfo({1, 1, 1, 1}, DataType);
1795 
1796  Connect(input, layer, tensorInfo);
1797  Connect(layer, output, tensorInfo);
1798 
1799  CreateTensorHandles(graph, factory);
1800 
1801  // Makes the workload and checks it.
1802  auto workload = MakeAndCheckWorkload<BatchToSpaceNdWorkload>(*layer, factory);
1803 
1804  BatchToSpaceNdQueueDescriptor queueDescriptor = workload->GetData();
1805  CHECK(queueDescriptor.m_Inputs.size() == 1);
1806  CHECK(queueDescriptor.m_Outputs.size() == 1);
1807 
1808  return workload;
1809 }
1810 
1811 template <typename LogSoftmaxWorkload, armnn::DataType DataType>
1812 std::unique_ptr<LogSoftmaxWorkload> CreateLogSoftmaxWorkloadTest(armnn::IWorkloadFactory& factory,
1813  armnn::Graph& graph)
1814 {
1815  // Create the layer we're testing.
1816  LogSoftmaxDescriptor logSoftmaxDescriptor;
1817  // Set Axis to -1 if CL or Neon until further Axes are supported.
1819  {
1820  logSoftmaxDescriptor.m_Axis = -1;
1821  }
1822 
1823  Layer* const layer = graph.AddLayer<LogSoftmaxLayer>(logSoftmaxDescriptor, "layer");
1824  // Create extra layers.
1825  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1826  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1827 
1828  // Connect up
1829  armnn::TensorInfo tensorInfo({4, 1}, DataType);
1830 
1831  Connect(input, layer, tensorInfo);
1832  Connect(layer, output, tensorInfo);
1833  CreateTensorHandles(graph, factory);
1834 
1835  // Make the workload and checks it.
1836  auto workload = MakeAndCheckWorkload<LogSoftmaxWorkload>(*layer, factory);
1837 
1838  LogSoftmaxQueueDescriptor queueDescriptor = workload->GetData();
1839  CHECK(queueDescriptor.m_Inputs.size() == 1);
1840  CHECK(queueDescriptor.m_Outputs.size() == 1);
1841 
1842  // Return so we can do extra, backend-specific tests.
1843  return workload;
1844 }
1845 
1846 template <typename L2NormalizationWorkload, armnn::DataType DataType>
1847 std::unique_ptr<L2NormalizationWorkload> CreateL2NormalizationWorkloadTest(armnn::IWorkloadFactory& factory,
1848  armnn::Graph& graph, DataLayout dataLayout = DataLayout::NCHW)
1849 {
1850  // Creates the layer we're testing.
1851  L2NormalizationDescriptor layerDesc;
1852  layerDesc.m_DataLayout = dataLayout;
1853 
1854  Layer* const layer = graph.AddLayer<L2NormalizationLayer>(layerDesc, "l2norm");
1855 
1856  // Creates extra layers.
1857  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1858  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1859 
1860  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
1861  TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
1862  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
1863  TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
1864 
1865  // Connects up.
1866  armnn::TensorInfo inputTensorInfo(inputShape, DataType);
1867  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
1868  Connect(input, layer, inputTensorInfo);
1869  Connect(layer, output, outputTensorInfo);
1870  CreateTensorHandles(graph, factory);
1871 
1872  // Makes the workload and checks it.
1873  auto workload = MakeAndCheckWorkload<L2NormalizationWorkload>(*layer, factory);
1874 
1875  L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
1876  CHECK((queueDescriptor.m_Parameters.m_DataLayout == dataLayout));
1877  CHECK(queueDescriptor.m_Inputs.size() == 1);
1878  CHECK(queueDescriptor.m_Outputs.size() == 1);
1879 
1880  // Returns so we can do extra, backend-specific tests.
1881  return workload;
1882 }
1883 
1884 template <typename ReshapeWorkload, armnn::DataType DataType>
1885 std::unique_ptr<ReshapeWorkload> CreateReshapeWorkloadTest(armnn::IWorkloadFactory& factory,
1886  armnn::Graph& graph)
1887 {
1888  // Creates the layer we're testing.
1889  TensorShape outputShape({ 1, 4 });
1890  ReshapeDescriptor reshapeDesc;
1891  reshapeDesc.m_TargetShape = outputShape;
1892  Layer* const layer = graph.AddLayer<ReshapeLayer>(reshapeDesc, "layer");
1893 
1894  // Creates extra layers.
1895  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1896  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1897 
1898  // Connects up.
1899  armnn::TensorInfo inputTensorInfo({ 4, 1 }, DataType);
1900  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
1901  Connect(input, layer, inputTensorInfo);
1902  Connect(layer, output, outputTensorInfo);
1903  CreateTensorHandles(graph, factory);
1904 
1905  // Makes the workload and checks it.
1906  auto workload = MakeAndCheckWorkload<ReshapeWorkload>(*layer, factory);
1907 
1908  ReshapeQueueDescriptor queueDescriptor = workload->GetData();
1909  CHECK(queueDescriptor.m_Inputs.size() == 1);
1910  CHECK(queueDescriptor.m_Outputs.size() == 1);
1911 
1912  // Returns so we can do extra, backend-specific tests.
1913  return workload;
1914 }
1915 
1916 template <typename ConvertFp16ToFp32Float32Workload>
1917 std::unique_ptr<ConvertFp16ToFp32Float32Workload> CreateConvertFp16ToFp32WorkloadTest(
1918  armnn::IWorkloadFactory& factory, armnn::Graph& graph)
1919 {
1920  // Creates the layer we're testing.
1921  ConvertFp16ToFp32Layer* const layer = graph.AddLayer<ConvertFp16ToFp32Layer>("Fp16ToFp32Converter");
1922 
1923  // Creates extra layers.
1924  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1925  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1926 
1927  // Connects up.
1928  armnn::TensorInfo inputTensorInfo({1, 3, 2, 3}, armnn::DataType::Float16);
1929  armnn::TensorInfo outputTensorInfo({1, 3, 2, 3}, armnn::DataType::Float32);
1930  Connect(input, layer, inputTensorInfo);
1931  Connect(layer, output, outputTensorInfo);
1932  CreateTensorHandles(graph, factory);
1933 
1934  // Makes the workload and checks it.
1935  auto workload = MakeAndCheckWorkload<ConvertFp16ToFp32Float32Workload>(*layer, factory);
1936 
1937  ConvertFp16ToFp32QueueDescriptor queueDescriptor = workload->GetData();
1938  CHECK(queueDescriptor.m_Inputs.size() == 1);
1939  CHECK(queueDescriptor.m_Outputs.size() == 1);
1940 
1941  // Returns so we can do extra, backend-specific tests.
1942  return workload;
1943 }
1944 
1945 template <typename ConvertFp32ToFp16Float16Workload>
1946 std::unique_ptr<ConvertFp32ToFp16Float16Workload> CreateConvertFp32ToFp16WorkloadTest(
1947  armnn::IWorkloadFactory& factory, armnn::Graph& graph)
1948 {
1949  // Creates the layer we're testing.
1950  ConvertFp32ToFp16Layer* const layer = graph.AddLayer<ConvertFp32ToFp16Layer>("Fp32ToFp16Converter");
1951 
1952  // Creates extra layers.
1953  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1954  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1955 
1956  // Connects up.
1957  armnn::TensorInfo inputTensorInfo({1, 3, 2, 3}, armnn::DataType::Float32);
1958  armnn::TensorInfo outputTensorInfo({1, 3, 2, 3}, armnn::DataType::Float16);
1959  Connect(input, layer, inputTensorInfo);
1960  Connect(layer, output, outputTensorInfo);
1961  CreateTensorHandles(graph, factory);
1962 
1963  // Makes the workload and checks it.
1964  auto workload = MakeAndCheckWorkload<ConvertFp32ToFp16Float16Workload>(*layer, factory);
1965 
1966  ConvertFp32ToFp16QueueDescriptor queueDescriptor = workload->GetData();
1967  CHECK(queueDescriptor.m_Inputs.size() == 1);
1968  CHECK(queueDescriptor.m_Outputs.size() == 1);
1969 
1970  // Returns so we can do extra, backend-specific tests.
1971  return workload;
1972 }
1973 
1974 template <typename MeanWorkload, armnn::DataType DataType>
1975 std::unique_ptr<MeanWorkload> CreateMeanWorkloadTest(armnn::IWorkloadFactory& factory, armnn::Graph& graph)
1976 {
1977  // Reduce along the first and second dimensions, and do not keep the reduced dimensions.
1978  MeanDescriptor descriptor({ 1, 2 }, false);
1979 
1980  // Creates the layer we're testing.
1981  Layer* const layer = graph.AddLayer<MeanLayer>(descriptor, "mean");
1982 
1983  // Creates extra layers.
1984  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
1985  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
1986 
1987  // Connects up.
1988  armnn::TensorInfo inputTensorInfo({ 1, 3, 7, 4 }, DataType);
1989  armnn::TensorInfo outputTensorInfo({ 1, 4 }, DataType);
1990  Connect(input, layer, inputTensorInfo);
1991  Connect(layer, output, outputTensorInfo);
1992  CreateTensorHandles(graph, factory);
1993 
1994  // Makes the workload and checks it.
1995  auto workload = MakeAndCheckWorkload<MeanWorkload>(*layer, factory);
1996 
1997  MeanQueueDescriptor queueDescriptor = workload->GetData();
1998  CHECK(queueDescriptor.m_Parameters.m_Axis == descriptor.m_Axis);
1999  CHECK(queueDescriptor.m_Parameters.m_KeepDims == descriptor.m_KeepDims);
2000  CHECK(queueDescriptor.m_Inputs.size() == 1);
2001  CHECK(queueDescriptor.m_Outputs.size() == 1);
2002 
2003  // Returns so we can do extra, backend-specific tests.
2004  return workload;
2005 }
2006 
2007 template<typename ConcatWorkload, armnn::DataType DataType>
2008 std::unique_ptr<ConcatWorkload> CreateConcatWorkloadTest(armnn::IWorkloadFactory &factory,
2009  armnn::Graph &graph,
2010  const armnn::TensorShape &outputShape,
2011  unsigned int concatAxis)
2012 {
2013  armnn::TensorInfo inputTensorInfo({ 2, 3, 2, 5 }, DataType);
2014  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
2015 
2016  // Constructs the graph.
2017  Layer* const input0 = graph.AddLayer<InputLayer>(0, "input0");
2018  Layer* const input1 = graph.AddLayer<InputLayer>(1, "input1");
2019  armnn::OriginsDescriptor descriptor;
2020 
2021  std::vector<armnn::TensorShape> inputShapes{{ 2, 3, 2, 5 }, { 2, 3, 2, 5 }};
2022 
2023  descriptor = CreateDescriptorForConcatenation(inputShapes.begin(),
2024  inputShapes.end(),
2025  concatAxis);
2026 
2027  // create concat layer
2028  Layer* const concat = graph.AddLayer<ConcatLayer>(descriptor, "concat");
2029  CHECK(concat);
2030 
2031  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
2032 
2033  // Adds connections.
2034  // connect input0 to concat
2035  Connect(input0, concat, inputTensorInfo, 0, 0);
2036  // connect input1 to concat
2037  Connect(input1, concat, inputTensorInfo, 0, 1);
2038  // connect concat to output
2039  Connect(concat, output, outputTensorInfo, 0, 0);
2040 
2041  // create tensor handles
2042  CreateTensorHandles(graph, factory);
2043 
2044  // create concat workload
2045  auto workloadConcat = MakeAndCheckWorkload<ConcatWorkload>(*concat, factory);
2046  CHECK(workloadConcat);
2047 
2048  return workloadConcat;
2049 }
2050 
2051 template <typename PreCompiledWorkload, armnn::DataType dataType>
2052 std::pair<armnn::IOptimizedNetworkPtr, std::unique_ptr<PreCompiledWorkload>> CreatePreCompiledWorkloadTest(
2053  armnn::IWorkloadFactory& factory,
2054  armnn::Graph& graph,
2055  bool biasEnabled = false)
2056 {
2057  IgnoreUnused(graph);
2058 
2059  // build up the structure of the network
2061 
2062  // Add an input layer
2063  armnn::IConnectableLayer* const inputLayer = net->AddInputLayer(0, "input layer");
2064  CHECK(inputLayer);
2065 
2066  // ArmNN weights tensor shape is OIHW (out channels, in channels, height, width) for NCHW
2067  // ArmNN weights tensor shape is OHWI (out channels, height, width, in channels) for NHWC
2068  // this test is using NHWC, so the weights shape is OHWI
2069  TensorInfo weightsTensorInfo(TensorShape({16, 1, 1, 16}), dataType, 0.9f, 0, true);
2070  unsigned int weightsLength = weightsTensorInfo.GetNumElements();
2071 
2072  using WeightType = armnn::ResolveType<dataType>;
2073  std::vector<WeightType> convWeightsData(weightsLength);
2074  for (unsigned int i = 0; i < weightsLength; ++i)
2075  {
2076  convWeightsData[i] = static_cast<WeightType>(i);
2077  }
2078 
2079  armnn::ConstTensor weights(weightsTensorInfo, convWeightsData);
2080 
2081  // Add a layer that can be used in the PreCompiled layer
2082  armnn::Convolution2dDescriptor convDesc2d;
2083  convDesc2d.m_StrideX = 1;
2084  convDesc2d.m_StrideY = 1;
2085  convDesc2d.m_BiasEnabled = biasEnabled;
2087 
2088 
2089  const std::string convLayerName("conv layer");
2090 
2091  armnn::IConnectableLayer* convLayer = net->AddConvolution2dLayer(convDesc2d, convLayerName.c_str());
2092 
2093  IConnectableLayer* weightsLayer = net->AddConstantLayer(weights);
2094  weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
2095  weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1u));
2096 
2097  if (biasEnabled)
2098  {
2099  constexpr armnn::DataType biasDataType = ( dataType == armnn::DataType::QAsymmU8) ?
2101 
2102  TensorInfo biasTensorInfo(TensorShape({16}), biasDataType, 0.9f * 0.9f, 0, true);
2103  unsigned int biasLength = biasTensorInfo.GetNumElements();
2104 
2105  using BiasType = armnn::ResolveType<biasDataType>;
2106  std::vector<BiasType> biasData(biasLength);
2107  std::fill(biasData.begin(), biasData.end(), static_cast<BiasType>(0));
2108 
2109  armnn::ConstTensor biases(biasTensorInfo, biasData);
2110 
2111  IConnectableLayer* biasLayer = net->AddConstantLayer(biases);
2112 
2113  biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
2114  biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2u));
2115  }
2116 
2117  CHECK(convLayer);
2118 
2119  // Add an output layer
2120  armnn::IConnectableLayer* const outputLayer = net->AddOutputLayer(0, "output layer");
2121  CHECK(outputLayer);
2122 
2123  // set the tensors in the network (NHWC format)
2124  TensorInfo inputTensorInfo(TensorShape({ 1, 16, 16, 16 }), dataType);
2125  if (dataType == armnn::DataType::QAsymmU8)
2126  {
2127  inputTensorInfo.SetQuantizationOffset(0);
2128  inputTensorInfo.SetQuantizationScale(0.9f);
2129  }
2130 
2131  TensorInfo outputTensorInfo(TensorShape({1, 16, 16, 16}), dataType);
2132  if (dataType == armnn::DataType::QAsymmU8)
2133  {
2134  outputTensorInfo.SetQuantizationOffset(0);
2135  outputTensorInfo.SetQuantizationScale(0.9f);
2136  }
2137 
2138  // Connect the layers
2139  inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2140  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2141 
2142  convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2143  convLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2144 
2145  // Optimize the network for the backend supported by the factory
2146  std::vector<armnn::BackendId> backends = {factory.GetBackendId()};
2148  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
2149  armnn::OptimizerOptions optimizerOptions;
2150  armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec(),
2151  optimizerOptions);
2152  CHECK(optimizedNet != nullptr);
2153 
2154  // Find the PreCompiled layer in the optimised graph
2155  armnn::Graph& optimisedGraph = GetGraphForTesting(optimizedNet.get());
2156  Layer* preCompiledLayer = nullptr;
2157  for (auto& layer : optimisedGraph)
2158  {
2159  if (layer->GetType() == LayerType::PreCompiled)
2160  {
2161  preCompiledLayer = layer;
2162  }
2163  }
2164  CHECK(preCompiledLayer != nullptr);
2165 
2166  // Create the TensorHandles.
2167  CreateTensorHandles(optimisedGraph, factory);
2168 
2169  // Make the workload and check it.
2170  auto workload = MakeAndCheckWorkload<PreCompiledWorkload>(*preCompiledLayer, factory);
2171 
2172  PreCompiledQueueDescriptor queueDescriptor = workload->GetData();
2173  CHECK(queueDescriptor.m_Inputs.size() == 1);
2174  CHECK(queueDescriptor.m_Outputs.size() == 1);
2175 
2176  // Returns the workload so we can do extra, backend-specific tests.
2177  // NOTE: We need to return the optimised network as well, otherwise it gets
2178  // out of scope and the tensor handles get destructed
2179  return std::make_pair(std::move(optimizedNet), std::move(workload));
2180 }
2181 
2182 template<typename ConstantWorkload, armnn::DataType DataType>
2183 std::unique_ptr<ConstantWorkload> CreateConstantWorkloadTest(armnn::IWorkloadFactory& factory,
2184  armnn::Graph& graph,
2185  const armnn::TensorShape& outputShape)
2186 {
2187  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
2188 
2189  // create constant layer
2190  auto constant = graph.AddLayer<ConstantLayer>("constant");
2191  CHECK(constant);
2192  constant->m_LayerOutput = std::make_unique<ScopedTensorHandle>(outputTensorInfo);
2193 
2194  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
2195 
2196  // Adds connections.
2197  // connect constant to output
2198  Connect(constant, output, outputTensorInfo, 0, 0);
2199 
2200  // create tensor handles
2201  CreateTensorHandles(graph, factory);
2202 
2203  // create Constant workload"
2204  auto workloadConstant = MakeAndCheckWorkload<ConstantWorkload>(*constant, factory);
2205  CHECK(workloadConstant);
2206 
2207  return workloadConstant;
2208 }
2209 
2210 template <typename PreluWorkload>
2211 std::unique_ptr<PreluWorkload> CreatePreluWorkloadTest(armnn::IWorkloadFactory& factory,
2212  armnn::Graph& graph,
2213  const armnn::TensorShape& inputShape,
2214  const armnn::TensorShape& alphaShape,
2215  const armnn::TensorShape& outputShape,
2216  armnn::DataType dataType)
2217 {
2218  // Creates the PReLU layer
2219  Layer* const layer = graph.AddLayer<PreluLayer>("prelu");
2220  CHECK(layer != nullptr);
2221 
2222  // Creates extra layers
2223  Layer* const input = graph.AddLayer<InputLayer> (0, "input");
2224  Layer* const alpha = graph.AddLayer<InputLayer> (1, "alpha");
2225  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
2226  CHECK(input != nullptr);
2227  CHECK(alpha != nullptr);
2228  CHECK(output != nullptr);
2229 
2230  // Connects up
2231  armnn::TensorInfo inputTensorInfo (inputShape, dataType);
2232  armnn::TensorInfo alphaTensorInfo (alphaShape, dataType);
2233  armnn::TensorInfo outputTensorInfo(outputShape, dataType);
2234  Connect(input, layer, inputTensorInfo, 0, 0);
2235  Connect(alpha, layer, alphaTensorInfo, 0, 1);
2236  Connect(layer, output, outputTensorInfo, 0, 0);
2237  CreateTensorHandles(graph, factory);
2238 
2239  // Makes the workload and checks it
2240  auto workload = MakeAndCheckWorkload<PreluWorkload>(*layer, factory);
2241 
2242  PreluQueueDescriptor queueDescriptor = workload->GetData();
2243  CHECK(queueDescriptor.m_Inputs.size() == 2);
2244  CHECK(queueDescriptor.m_Outputs.size() == 1);
2245 
2246  // Returns so we can do extra, backend-specific tests.
2247  return workload;
2248 }
2249 
2250 template <typename SpaceToDepthWorkload, armnn::DataType DataType>
2251 std::unique_ptr<SpaceToDepthWorkload> CreateSpaceToDepthWorkloadTest(armnn::IWorkloadFactory& factory,
2252  armnn::Graph& graph)
2253 {
2255  desc.m_BlockSize = 2;
2256  Layer* const layer = graph.AddLayer<SpaceToDepthLayer>(desc, "spaceToDepth");
2257 
2258  // Creates extra layers.
2259  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
2260  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
2261 
2262  // Connects up.
2263  armnn::TensorInfo inputTensorInfo({ 1, 2, 2, 1 }, DataType);
2264  armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 4 }, DataType);
2265 
2266  Connect(input, layer, inputTensorInfo);
2267  Connect(layer, output, outputTensorInfo);
2268 
2269  CreateTensorHandles(graph, factory);
2270 
2271  // Makes the workload and checks it.
2272  auto workload = MakeAndCheckWorkload<SpaceToDepthWorkload>(*layer, factory);
2273 
2274  SpaceToDepthQueueDescriptor queueDescriptor = workload->GetData();
2275  CHECK(queueDescriptor.m_Inputs.size() == 1);
2276  CHECK(queueDescriptor.m_Outputs.size() == 1);
2277 
2278  return workload;
2279 }
2280 
2281 template <typename StackWorkload, armnn::DataType DataType>
2282 std::unique_ptr<StackWorkload> CreateStackWorkloadTest(armnn::IWorkloadFactory& factory,
2283  armnn::Graph& graph,
2284  const armnn::TensorShape& inputShape,
2285  const armnn::TensorShape& outputShape,
2286  unsigned int axis,
2287  unsigned int numInputs)
2288 {
2289  armnn::TensorInfo inputTensorInfo(inputShape, DataType);
2290  armnn::TensorInfo outputTensorInfo(outputShape, DataType);
2291 
2292  // Constructs the Stack layer.
2293  armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
2294  Layer* const stackLayer = graph.AddLayer<StackLayer>(descriptor, "stack");
2295  CHECK(stackLayer != nullptr);
2296 
2297  // Constructs layer inputs and output.
2298  std::vector<Layer*> inputs;
2299  for (unsigned int i=0; i<numInputs; ++i)
2300  {
2301  inputs.push_back(graph.AddLayer<InputLayer>(
2302  static_cast<int>(i),
2303  ("input" + std::to_string(i)).c_str()
2304  ));
2305  CHECK(inputs[i] != nullptr);
2306  }
2307  Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
2308  CHECK(output != nullptr);
2309 
2310  // Adds connections.
2311  for (unsigned int i=0; i<numInputs; ++i)
2312  {
2313  Connect(inputs[i], stackLayer, inputTensorInfo, 0, i);
2314  }
2315  Connect(stackLayer, output, outputTensorInfo, 0, 0);
2316 
2317  CreateTensorHandles(graph, factory);
2318 
2319  auto stackWorkload = MakeAndCheckWorkload<StackWorkload>(*stackLayer, factory);
2320  StackQueueDescriptor queueDescriptor = stackWorkload->GetData();
2321  CHECK(queueDescriptor.m_Inputs.size() == numInputs);
2322  CHECK(queueDescriptor.m_Outputs.size() == 1);
2323 
2324  return stackWorkload;
2325 }
2326 
2327 } // Anonymous namespace
armnn::QLstmDescriptor::m_CellClip
float m_CellClip
Clipping threshold value for the cell state.
Definition: Descriptors.hpp:1361
armnn::QLstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1371
armnn::BatchNormalizationLayer::m_Mean
std::shared_ptr< ConstTensorHandle > m_Mean
A unique pointer to store Mean values.
Definition: BatchNormalizationLayer.hpp:19
armnn::Pooling2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:389
armnn::BatchNormalizationQueueDescriptor::m_Variance
const ConstTensorHandle * m_Variance
Definition: WorkloadData.hpp:317
armnn::Convolution2dDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:552
armnn::QuantizedLstmQueueDescriptor
Definition: WorkloadData.hpp:609
armnn::PreluLayer
Definition: PreluLayer.hpp:14
armnn::Convolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:550
armnn::L2NormalizationQueueDescriptor
Definition: WorkloadData.hpp:353
armnn::QLstmDescriptor::m_ProjectionClip
float m_ProjectionClip
Clipping threshold value for the projection.
Definition: Descriptors.hpp:1363
armnn::DataType::QAsymmU8
@ QAsymmU8
armnn::FullyConnectedDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:494
armnn::ConstantLayer
A layer that the constant data can be bound to.
Definition: ConstantLayer.hpp:15
armnn::QLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:589
armnn::NormalizationDescriptor
A NormalizationDescriptor for the NormalizationLayer.
Definition: Descriptors.hpp:737
armnn::QLstmDescriptor::m_ForgetIntermediateScale
float m_ForgetIntermediateScale
Forget intermediate quantization scale.
Definition: Descriptors.hpp:1375
armnn::BatchNormalizationDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:811
armnn::BatchNormalizationLayer
This layer represents a batch normalization operation.
Definition: BatchNormalizationLayer.hpp:15
armnn::IOptimizedNetworkPtr
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:253
armnn::ElementwiseUnaryDescriptor
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:109
armnn::DataLayout
DataLayout
Definition: Types.hpp:62
armnn::BatchNormalizationQueueDescriptor::m_Beta
const ConstTensorHandle * m_Beta
Definition: WorkloadData.hpp:318
DataLayoutIndexed.hpp
armnn::SoftmaxDescriptor
A SoftmaxDescriptor for the SoftmaxLayer.
Definition: Descriptors.hpp:157
armnn::QuantizedLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:628
Connect
void Connect(armnn::IConnectableLayer *from, armnn::IConnectableLayer *to, const armnn::TensorInfo &tensorInfo, unsigned int fromIndex, unsigned int toIndex)
Definition: TestUtils.cpp:14
armnn::Convolution2dDescriptor::m_PadBottom
uint32_t m_PadBottom
Padding bottom value in the height dimension.
Definition: Descriptors.hpp:540
armnn::StackDescriptor
A StackDescriptor for the StackLayer.
Definition: Descriptors.hpp:1198
armnn::LstmOptPeepholeParameters::m_CellToOutputWeights
std::shared_ptr< ConstTensorHandle > m_CellToOutputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Definition: LstmParameters.hpp:51
armnn::DataType::Float16
@ Float16
armnn::NormalizationQueueDescriptor
Definition: WorkloadData.hpp:247
armnn::OutputShapeRounding::Floor
@ Floor
armnn::ActivationDescriptor
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:36
armnn::TensorHandleFactoryRegistry
Definition: TensorHandleFactoryRegistry.hpp:23
armnn::IConnectableLayer
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
armnn::LstmDescriptor
An LstmDescriptor for the LstmLayer.
Definition: Descriptors.hpp:1049
armnn::SplitterLayer
This layer represents a split operation.
Definition: SplitterLayer.hpp:13
armnn::LstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:435
armnn::FullyConnectedDescriptor
A FullyConnectedDescriptor for the FullyConnectedLayer.
Definition: Descriptors.hpp:475
armnn::InputLayer
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: InputLayer.hpp:13
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:436
armnn::QLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:598
armnn::IWorkloadFactory::GetBackendId
virtual const BackendId & GetBackendId() const =0
armnn::QLstmBasicParameters::m_RecurrentToCellWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, outputSize] (QSymmS8).
Definition: QLstmLayer.hpp:26
armnn::Layer::SetBackendId
void SetBackendId(const BackendId &id) override
Set the backend of the IConnectableLayer.
Definition: Layer.hpp:278
armnn::ResolveType
typename ResolveTypeImpl< DT >::Type ResolveType
Definition: ResolveType.hpp:79
armnn::QLstmLayer
This layer represents a QLstm operation.
Definition: QLstmLayer.hpp:79
armnn::Compute::CpuAcc
@ CpuAcc
CPU Execution: NEON: ArmCompute.
armnn::Compute::GpuAcc
@ GpuAcc
GPU Execution: OpenCL: ArmCompute.
armnn::ResizeDescriptor
A ResizeDescriptor for the ResizeLayer.
Definition: Descriptors.hpp:932
armnn::DepthwiseConvolution2dQueueDescriptor
Depthwise Convolution 2D layer workload data.
Definition: WorkloadData.hpp:229
armnn::FullyConnectedDescriptor::m_ConstantWeights
bool m_ConstantWeights
Enable/disable constant weights and biases.
Definition: Descriptors.hpp:498
armnn::Pooling2dDescriptor::m_PoolHeight
uint32_t m_PoolHeight
Pooling height value.
Definition: Descriptors.hpp:385
armnn::ConstTensor
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
armnn::LstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:423
armnn::ConcatLayer
This layer represents a merge operation.
Definition: ConcatLayer.hpp:13
armnn::IRuntime::CreationOptions
Definition: IRuntime.hpp:85
armnn::MultiplicationLayer
This layer represents a multiplication operation.
Definition: MultiplicationLayer.hpp:14
PolymorphicDowncast.hpp
armnn::Layer
Definition: Layer.hpp:217
armnn::ConvertFp32ToFp16QueueDescriptor
Definition: WorkloadData.hpp:452
TestUtils.hpp
armnn::ModelOptions
std::vector< BackendOptions > ModelOptions
Definition: BackendOptions.hpp:18
armnnUtils::DataLayoutIndexed::GetWidthIndex
unsigned int GetWidthIndex() const
Definition: DataLayoutIndexed.hpp:25
armnn::IgnoreUnused
void IgnoreUnused(Ts &&...)
Definition: IgnoreUnused.hpp:14
armnn::DataType::Signed32
@ Signed32
armnn::LstmBasicParameters::m_RecurrentToOutputWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
Definition: LstmParameters.hpp:67
armnn::LstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
Definition: Descriptors.hpp:1093
armnn::Pooling2dDescriptor::m_PoolType
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
Definition: Descriptors.hpp:373
armnn::LstmLayer
This layer represents a LSTM operation.
Definition: LstmLayer.hpp:16
Assert.hpp
TensorHandle.hpp
armnn::ViewsDescriptor
A ViewsDescriptor for the SplitterLayer.
Definition: Descriptors.hpp:224
armnn::IWorkloadFactory
Definition: WorkloadFactory.hpp:22
armnn::DepthwiseConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:676
armnn::MeanDescriptor::m_Axis
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
Definition: Descriptors.hpp:1137
armnn::GetBiasDataType
DataType GetBiasDataType(DataType inputDataType)
Definition: WorkloadData.cpp:28
armnn::Convolution2dDescriptor::m_PadTop
uint32_t m_PadTop
Padding top value in the height dimension.
Definition: Descriptors.hpp:538
armnn::Pooling2dDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:395
armnn::QLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:587
armnn::Convolution2dDescriptor::m_PadRight
uint32_t m_PadRight
Padding right value in the width dimension.
Definition: Descriptors.hpp:536
WorkloadFactory.hpp
armnn::IConnectableLayer::GetOutputSlot
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
armnn::LstmBasicParameters::m_OutputGateBias
std::shared_ptr< ConstTensorHandle > m_OutputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Definition: LstmParameters.hpp:73
armnn::ActivationLayer
This layer represents an activation operation with the specified activation function.
Definition: ActivationLayer.hpp:12
armnn::DataType::QAsymmS8
@ QAsymmS8
armnn::Pooling2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:387
armnn::DepthwiseConvolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:668
armnn::ReshapeLayer
This layer represents a reshape operation.
Definition: ReshapeLayer.hpp:15
armnn::LogSoftmaxLayer
This layer represents a log softmax operation.
Definition: LogSoftmaxLayer.hpp:14
armnn::IOutputSlot::Connect
virtual int Connect(IInputSlot &destination)=0
armnn::QLstmQueueDescriptor
Definition: WorkloadData.hpp:557
armnn::TensorInfo::SetConstant
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:514
armnn::NormalizationDescriptor::m_NormMethodType
NormalizationAlgorithmMethod m_NormMethodType
Normalization method algorithm to use (LocalBrightness, LocalContrast).
Definition: Descriptors.hpp:763
armnn::QLstmDescriptor::m_CellIntermediateScale
float m_CellIntermediateScale
Cell intermediate quantization scale.
Definition: Descriptors.hpp:1377
armnn::DepthwiseConvolution2dDescriptor::m_PadLeft
uint32_t m_PadLeft
Padding left value in the width dimension.
Definition: Descriptors.hpp:660
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::LstmLayer::m_PeepholeParameters
LstmOptPeepholeParameters m_PeepholeParameters
Definition: LstmLayer.hpp:23
armnn::QLstmDescriptor::m_OutputIntermediateScale
float m_OutputIntermediateScale
Output intermediate quantization scale.
Definition: Descriptors.hpp:1379
armnn::NormalizationDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:773
armnn::DepthwiseConvolution2dDescriptor::m_PadTop
uint32_t m_PadTop
Padding top value in the height dimension.
Definition: Descriptors.hpp:664
armnn::BatchToSpaceNdDescriptor
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
Definition: Descriptors.hpp:843
armnn::IConnectableLayer::GetInputSlot
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
armnn::QLstmOptLayerNormParameters::m_OutputLayerNormWeights
std::shared_ptr< ConstTensorHandle > m_OutputLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units] (QSymmS16).
Definition: QLstmLayer.hpp:75
armnn::SpaceToDepthDescriptor
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
Definition: Descriptors.hpp:1022
armnn::TensorInfo::SetQuantizationOffset
void SetQuantizationOffset(int32_t offset)
Definition: Tensor.cpp:489
armnn::BatchNormalizationQueueDescriptor
Definition: WorkloadData.hpp:306
armnn::QLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:597
armnn::QLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:596
armnn::QuantizedLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:640
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::FullyConnectedQueueDescriptor
Definition: WorkloadData.hpp:180
armnn::LayerType
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below.
Definition: Types.hpp:466
armnn::BatchNormalizationQueueDescriptor::m_Gamma
const ConstTensorHandle * m_Gamma
Definition: WorkloadData.hpp:319
armnn::ResizeDescriptor::m_TargetHeight
uint32_t m_TargetHeight
Target height value.
Definition: Descriptors.hpp:956
armnn::DataLayout::NCHW
@ NCHW
armnn::LstmQueueDescriptor
Definition: WorkloadData.hpp:395
armnn::QLstmBasicParameters::m_RecurrentToForgetWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, outputSize] (QSymmS8).
Definition: QLstmLayer.hpp:24
armnn::SubtractionLayer
This layer represents a subtraction operation.
Definition: SubtractionLayer.hpp:14
armnn::DepthwiseConvolution2dDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:678
armnn::NormalizationLayer
This layer represents a normalization operation.
Definition: NormalizationLayer.hpp:13
armnn::SoftmaxDescriptor::m_Axis
int m_Axis
Scalar, defaulted to the last index (-1), specifying the dimension the activation will be performed o...
Definition: Descriptors.hpp:172
armnn::QuantizedLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:629
armnn::LstmOptPeepholeParameters::m_CellToForgetWeights
std::shared_ptr< ConstTensorHandle > m_CellToForgetWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Definition: LstmParameters.hpp:49
armnn::NormalizationAlgorithmChannel::Across
@ Across
armnn::Convolution2dDescriptor::m_PadLeft
uint32_t m_PadLeft
Padding left value in the width dimension.
Definition: Descriptors.hpp:534
armnn::DepthwiseConvolution2dDescriptor
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
Definition: Descriptors.hpp:627
armnn::MeanDescriptor
A MeanDescriptor for the MeanLayer.
Definition: Descriptors.hpp:1119
armnn::QLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:585
armnn::NormalizationAlgorithmMethod::LocalBrightness
@ LocalBrightness
Krichevsky 2012: Local Brightness Normalization.
armnn::NormalizationDescriptor::m_NormSize
uint32_t m_NormSize
Depth radius value.
Definition: Descriptors.hpp:765
armnn::QLstmBasicParameters::m_InputToCellWeights
std::shared_ptr< ConstTensorHandle > m_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, inputSize] (QSymmS8).
Definition: QLstmLayer.hpp:19
armnn::PreluQueueDescriptor
Definition: WorkloadData.hpp:534
armnn::Pooling2dDescriptor::m_PadBottom
uint32_t m_PadBottom
Padding bottom value in the height dimension.
Definition: Descriptors.hpp:381
armnn::QLstmLayer::m_LayerNormParameters
QLstmOptLayerNormParameters m_LayerNormParameters
Definition: QLstmLayer.hpp:87
armnn::QLstmBasicParameters::m_RecurrentToOutputWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, outputSize] (QSymmS8).
Definition: QLstmLayer.hpp:28
armnn::LstmBasicParameters::m_ForgetGateBias
std::shared_ptr< ConstTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Definition: LstmParameters.hpp:69
armnn::L2NormalizationDescriptor
A L2NormalizationDescriptor for the L2NormalizationLayer.
Definition: Descriptors.hpp:777
armnn::DataType::Float32
@ Float32
armnn::IWorkloadFactory::IsLayerSupported
static bool IsLayerSupported(const BackendId &backendId, const IConnectableLayer &layer, Optional< DataType > dataType, std::string &outReasonIfUnsupported)
Definition: WorkloadFactory.cpp:1518
armnn::BatchNormalizationQueueDescriptor::m_Mean
const ConstTensorHandle * m_Mean
Definition: WorkloadData.hpp:316
armnn::LstmLayer::m_BasicParameters
LstmBasicParameters m_BasicParameters
Definition: LstmLayer.hpp:20
armnn::QuantizedLstmLayer
This layer represents a QuantizedLstm operation.
Definition: QuantizedLstmLayer.hpp:45
armnn::LstmBasicParameters::m_CellBias
std::shared_ptr< ConstTensorHandle > m_CellBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Definition: LstmParameters.hpp:71
armnn::QuantizedLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:630
armnn::ResizeMethod::Bilinear
@ Bilinear
armnn::LstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1095
armnn::GetGraphForTesting
Graph & GetGraphForTesting(IOptimizedNetwork *optNet)
Definition: TestUtils.cpp:49
armnn::BatchToSpaceNdLayer
This layer represents a BatchToSpaceNd operation.
Definition: BatchToSpaceNdLayer.hpp:13
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::StackQueueDescriptor
Definition: WorkloadData.hpp:152
armnn::ResizeDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:961
armnn::SpaceToDepthDescriptor::m_BlockSize
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
Definition: Descriptors.hpp:1039
armnn::Convolution2dDescriptor
A Convolution2dDescriptor for the Convolution2dLayer.
Definition: Descriptors.hpp:502
armnn::PreCompiledQueueDescriptor
Definition: WorkloadData.hpp:507
armnn::UnaryOperation
UnaryOperation
Definition: Types.hpp:124
armnn::Pooling2dDescriptor::m_PoolWidth
uint32_t m_PoolWidth
Pooling width value.
Definition: Descriptors.hpp:383
armnn::BatchNormalizationDescriptor
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
Definition: Descriptors.hpp:796
armnn::QLstmDescriptor
A QLstmDescriptor for the QLstmLayer.
Definition: Descriptors.hpp:1327
armnn::ActivationDescriptor::m_A
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH,...
Definition: Descriptors.hpp:61
armnn::LogSoftmaxQueueDescriptor
Definition: WorkloadData.hpp:358
armnn::QLstmLayer::m_BasicParameters
QLstmBasicParameters m_BasicParameters
Definition: QLstmLayer.hpp:83
armnn::ConvertFp16ToFp32QueueDescriptor
Definition: WorkloadData.hpp:447
armnn::SoftmaxLayer
This layer represents a softmax operation.
Definition: SoftmaxLayer.hpp:13
armnn::QuantizedLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:631
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:636
armnn::QueueDescriptor::GetAdditionalInformation
const T * GetAdditionalInformation() const
Definition: WorkloadData.hpp:47
armnn::ResizeDescriptor::m_Method
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
Definition: Descriptors.hpp:959
armnn::ConstTensorHandle::GetTensorInfo
const TensorInfo & GetTensorInfo() const
Definition: TensorHandle.hpp:40
armnn::Pooling2dDescriptor::m_PadLeft
uint32_t m_PadLeft
Padding left value in the width dimension.
Definition: Descriptors.hpp:375
armnn::QLstmDescriptor::m_HiddenStateScale
float m_HiddenStateScale
Hidden State quantization scale.
Definition: Descriptors.hpp:1383
armnn::QLstmDescriptor::m_HiddenStateZeroPoint
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
Definition: Descriptors.hpp:1381
armnn::FullyConnectedLayer
This layer represents a fully connected operation.
Definition: FullyConnectedLayer.hpp:15
armnn::QLstmBasicParameters::m_CellBias
std::shared_ptr< ConstTensorHandle > m_CellBias
A unique pointer to represent 1D bias tensor with dimensions [num_units] (int32).
Definition: QLstmLayer.hpp:33
armnn::ReshapeQueueDescriptor
Definition: WorkloadData.hpp:375
armnn::DataLayout::NHWC
@ NHWC
armnn::QuantizedLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:641
armnn::ConstantLayer::m_LayerOutput
std::shared_ptr< ConstTensorHandle > m_LayerOutput
Definition: ConstantLayer.hpp:44
armnn::Layer::CreateTensorHandles
virtual void CreateTensorHandles(const TensorHandleFactoryRegistry &registry, const IWorkloadFactory &factory, const bool IsMemoryManaged=true)
Definition: Layer.cpp:279
armnn::Pooling2dDescriptor::m_PadTop
uint32_t m_PadTop
Padding top value in the height dimension.
Definition: Descriptors.hpp:379
armnn::ActivationDescriptor::m_Function
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu,...
Definition: Descriptors.hpp:59
armnn::Convolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:542
armnn::Layer::SetAdditionalInfoForObject
void SetAdditionalInfoForObject(const AdditionalInfoObjectPtr &additionalInfo)
Definition: Layer.hpp:360
armnn::BatchNormalizationLayer::m_Beta
std::shared_ptr< ConstTensorHandle > m_Beta
A unique pointer to store Beta values.
Definition: BatchNormalizationLayer.hpp:23
armnn::Pooling2dLayer
This layer represents a pooling 2d operation.
Definition: Pooling2dLayer.hpp:13
armnn::NormalizationDescriptor::m_K
float m_K
Kappa value used for the across channel normalization equation.
Definition: Descriptors.hpp:771
armnn::Layer::GetDataType
DataType GetDataType() const
Definition: Layer.cpp:313
armnn::INetwork::Create
static INetworkPtr Create(const NetworkOptions &networkOptions={})
Definition: Network.cpp:452
armnn::LstmBasicParameters::m_RecurrentToForgetWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
Definition: LstmParameters.hpp:63
armnn::NormalizationDescriptor::m_Beta
float m_Beta
Beta value for the normalization equation.
Definition: Descriptors.hpp:769
armnn::SplitterQueueDescriptor
Definition: WorkloadData.hpp:111
armnn::LstmDescriptor::m_ClippingThresCell
float m_ClippingThresCell
Clipping threshold value for the cell state.
Definition: Descriptors.hpp:1089
armnn::Layer::GetAdditionalInformation
std::shared_ptr< T > GetAdditionalInformation() const
Definition: Layer.hpp:355
armnn::OriginsDescriptor
An OriginsDescriptor for the ConcatLayer.
Definition: Descriptors.hpp:181
armnn::ReshapeDescriptor
A ReshapeDescriptor for the ReshapeLayer.
Definition: Descriptors.hpp:970
armnn::QLstmOptLayerNormParameters::m_CellLayerNormWeights
std::shared_ptr< ConstTensorHandle > m_CellLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units] (QSymmS16).
Definition: QLstmLayer.hpp:73
armnn::QueueDescriptorWithParameters::m_Parameters
LayerDescriptor m_Parameters
Definition: WorkloadData.hpp:66
armnn::DepthwiseConvolution2dLayer
This layer represents a depthwise convolution 2d operation.
Definition: DepthwiseConvolution2dLayer.hpp:15
armnn::DataType
DataType
Definition: Types.hpp:48
armnn::FullyConnectedDescriptor::m_TransposeWeightMatrix
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
Definition: Descriptors.hpp:496
armnn::Graph
Definition: Graph.hpp:30
armnn::L2NormalizationDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:792
Network.hpp
armnn::L2NormalizationLayer
This layer represents a L2 normalization operation.
Definition: L2NormalizationLayer.hpp:13
armnn::QLstmOptLayerNormParameters::m_ForgetLayerNormWeights
std::shared_ptr< ConstTensorHandle > m_ForgetLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units] (QSymmS16).
Definition: QLstmLayer.hpp:71
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::IOutputSlot::SetTensorInfo
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
armnnUtils::DataLayoutIndexed
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
Definition: DataLayoutIndexed.hpp:17
armnn::SpaceToDepthQueueDescriptor
Definition: WorkloadData.hpp:385
armnn::BatchToSpaceNdQueueDescriptor
Definition: WorkloadData.hpp:457
armnn::QLstmBasicParameters::m_ForgetGateBias
std::shared_ptr< ConstTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D bias tensor with dimensions [num_units] (int32).
Definition: QLstmLayer.hpp:31
armnn::QLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:586
armnn::DepthwiseConvolution2dDescriptor::m_PadRight
uint32_t m_PadRight
Padding right value in the width dimension.
Definition: Descriptors.hpp:662
armnn::Pooling2dDescriptor
A Pooling2dDescriptor for the Pooling2dLayer.
Definition: Descriptors.hpp:339
armnn::SplitterQueueDescriptor::m_ViewOrigins
std::vector< ViewOrigin > m_ViewOrigins
Definition: WorkloadData.hpp:124
armnn::LstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1097
armnn::LstmBasicParameters::m_InputToCellWeights
std::shared_ptr< ConstTensorHandle > m_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
Definition: LstmParameters.hpp:59
armnn::AdditionLayer
This layer represents an addition operation.
Definition: AdditionLayer.hpp:13
armnn::Convolution2dQueueDescriptor
Definition: WorkloadData.hpp:205
armnn::PoolingAlgorithm::Average
@ Average
armnn::QLstmDescriptor::m_InputIntermediateScale
float m_InputIntermediateScale
Input intermediate quantization scale.
Definition: Descriptors.hpp:1373
armnn::LstmBasicParameters::m_InputToOutputWeights
std::shared_ptr< ConstTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
Definition: LstmParameters.hpp:61
armnn::MeanDescriptor::m_KeepDims
bool m_KeepDims
Enable/disable keep dimensions. If true, then the reduced dimensions that are of length 1 are kept.
Definition: Descriptors.hpp:1139
armnn::Pooling2dDescriptor::m_PadRight
uint32_t m_PadRight
Padding right value in the width dimension.
Definition: Descriptors.hpp:377
armnnUtils::DataLayoutIndexed::GetHeightIndex
unsigned int GetHeightIndex() const
Definition: DataLayoutIndexed.hpp:24
armnn::LstmBasicParameters::m_InputToForgetWeights
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
Definition: LstmParameters.hpp:57
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:635
armnn::QLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:591
armnn::DataType::QSymmS8
@ QSymmS8
armnn::QLstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
Definition: Descriptors.hpp:1365
armnn::ActivationQueueDescriptor
Definition: WorkloadData.hpp:158
armnn::MeanLayer
This layer represents a mean operation.
Definition: MeanLayer.hpp:14
armnn::Layer::CreateWorkload
virtual std::unique_ptr< IWorkload > CreateWorkload(const IWorkloadFactory &factory) const =0
armnn::Pooling2dQueueDescriptor
Definition: WorkloadData.hpp:192
armnn::DepthwiseConvolution2dDescriptor::m_PadBottom
uint32_t m_PadBottom
Padding bottom value in the height dimension.
Definition: Descriptors.hpp:666
ResolveType.hpp
armnn::ConvertFp16ToFp32Layer
This layer converts data type Float 16 to Float 32.
Definition: ConvertFp16ToFp32Layer.hpp:14
armnn::QLstmBasicParameters::m_InputToOutputWeights
std::shared_ptr< ConstTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, inputSize] (QSymmS8).
Definition: QLstmLayer.hpp:21
armnn::QueueDescriptor::m_Outputs
std::vector< ITensorHandle * > m_Outputs
Definition: WorkloadData.hpp:27
armnn::NormalizationDescriptor::m_NormChannelType
NormalizationAlgorithmChannel m_NormChannelType
Normalization channel algorithm to use (Across, Within).
Definition: Descriptors.hpp:761
armnn::INetworkPtr
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:252
armnn::CreateDescriptorForConcatenation
OriginsDescriptor CreateDescriptorForConcatenation(TensorShapeIt first, TensorShapeIt last, unsigned int concatenationDimension)
Convenience template to create an OriginsDescriptor to use when creating a ConcatLayer for performing...
Definition: Descriptors.hpp:268
armnn::LstmDescriptor::m_ActivationFunc
uint32_t m_ActivationFunc
The activation function to use.
Definition: Descriptors.hpp:1087
armnn::LstmDescriptor::m_ClippingThresProj
float m_ClippingThresProj
Clipping threshold value for the projection.
Definition: Descriptors.hpp:1091
armnn::DataType::QSymmS16
@ QSymmS16
armnn::QLstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1367
armnn::BatchNormalizationDescriptor::m_Eps
float m_Eps
Value to add to the variance. Used to avoid dividing by zero.
Definition: Descriptors.hpp:809
armnn::ActivationDescriptor::m_B
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
Definition: Descriptors.hpp:63
armnn::SoftmaxQueueDescriptor
Definition: WorkloadData.hpp:105
armnn::ResizeLayer
This layer represents a resize operation.
Definition: ResizeLayer.hpp:13
armnn::DepthwiseConvolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:670
armnn::LstmBasicParameters::m_RecurrentToCellWeights
std::shared_ptr< ConstTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
Definition: LstmParameters.hpp:65
armnn::ActivationFunction::ReLu
@ ReLu
armnn::QLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:590
IgnoreUnused.hpp
armnn::IRuntime::Create
static IRuntimePtr Create(const CreationOptions &options)
Definition: Runtime.cpp:52
armnn::QLstmBasicParameters::m_InputToForgetWeights
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, inputSize] (QSymmS8).
Definition: QLstmLayer.hpp:17
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:633
armnn::QuantizedLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:639
WorkloadData.hpp
std
Definition: BackendId.hpp:149
armnn::Convolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:544
armnn::Convolution2dLayer
This layer represents a convolution 2d operation.
Definition: Convolution2dLayer.hpp:15
armnn::Graph::AddLayer
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
Definition: Graph.hpp:456
armnn::MeanQueueDescriptor
Definition: WorkloadData.hpp:283
armnn::ConvertFp32ToFp16Layer
This layer converts data type Float 32 to Float 16.
Definition: ConvertFp32ToFp16Layer.hpp:13
armnn::Optimize
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > & > messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1773
armnn::QuantizedLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:638
armnn::BatchNormalizationLayer::m_Gamma
std::shared_ptr< ConstTensorHandle > m_Gamma
A unique pointer to store Gamma values.
Definition: BatchNormalizationLayer.hpp:25
armnn::ReshapeDescriptor::m_TargetShape
TensorShape m_TargetShape
Target shape value.
Definition: Descriptors.hpp:986
armnn::SpaceToDepthLayer
This layer represents a SpaceToDepth operation.
Definition: SpaceToDepthLayer.hpp:14
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:634
armnn::QLstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1369
armnn::ActivationFunction::BoundedReLu
@ BoundedReLu
min(a, max(b, input)) ReLu1 & ReLu6.
armnn::NormalizationDescriptor::m_Alpha
float m_Alpha
Alpha value for the normalization equation.
Definition: Descriptors.hpp:767
Graph.hpp
armnn::ElementwiseUnaryLayer
This layer represents a elementwiseUnary operation.
Definition: ElementwiseUnaryLayer.hpp:14
armnn::Graph::TopologicalSort
Graph & TopologicalSort()
Sorts layers in topological order and return this.
Definition: Graph.hpp:184
armnn::OptimizerOptions
ArmNN performs an optimization on each model/network before it gets loaded for execution.
Definition: INetwork.hpp:137
armnn::BatchNormalizationLayer::m_Variance
std::shared_ptr< ConstTensorHandle > m_Variance
A unique pointer to store Variance values.
Definition: BatchNormalizationLayer.hpp:21
armnn::IRuntimePtr
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:41
armnn::OutputLayer
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: OutputLayer.hpp:13
armnn::QLstmBasicParameters::m_OutputGateBias
std::shared_ptr< ConstTensorHandle > m_OutputGateBias
A unique pointer to represent 1D bias tensor with dimensions [num_units] (int32).
Definition: QLstmLayer.hpp:35
armnn::QueueDescriptor::m_Inputs
std::vector< ITensorHandle * > m_Inputs
Definition: WorkloadData.hpp:26
armnn::StackLayer
This layer represents a stack operation.
Definition: StackLayer.hpp:13
armnn::ResizeDescriptor::m_TargetWidth
uint32_t m_TargetWidth
Target width value.
Definition: Descriptors.hpp:954
armnn::LayerType::PreCompiled
@ PreCompiled
armnn::Pooling2dDescriptor::m_OutputShapeRounding
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
Definition: Descriptors.hpp:391
armnn::ActivationFunction
ActivationFunction
Definition: Types.hpp:86