ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TurboConvertConstDequantisationLayersToConstLayers.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2024 Arm Ltd and Contributors.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "Optimization.hpp"
8 #include "NetworkUtils.hpp"
9 
10 #include <armnn/Logging.hpp>
11 #include <armnnUtils/Permute.hpp>
12 
13 namespace armnn
14 {
15 namespace optimizations
16 {
17 
19 {
20 public:
21  void Run(Graph& graph, InputSlot& connection) const
22  {
23  Layer& base = connection.GetConnectedOutputSlot()->GetOwningLayer();
24  Layer& child = connection.GetOwningLayer();
25 
26  // Check the basic criteria for the optimization are met.
27  if ((base.GetType() == LayerType::Constant) && (child.GetType() == LayerType::Dequantize))
28  {
29  ReplaceConstDequantisationLayer(graph, PolymorphicDowncast<ConstantLayer*>(&base),
30  PolymorphicDowncast<DequantizeLayer*>(&child));
31  }
32  }
33 protected:
36 private:
37 
38  static void ReplaceConstDequantisationLayer(Graph&,
39  ConstantLayer* constantLayer,
40  DequantizeLayer* dequantizeLayer)
41  {
42  ARMNN_LOG(info) << "TurboConvertConstDequantisationLayersToConstLayersImpl::ReplaceConstDequantisationLayer()";
43  /**
44  * This optimisation is to find situations where a constant set of inputs is being provided to a Dequantization
45  * layer. In this case we don't want the overhead of Dequantizing the values on every inference, instead we
46  * want to Dequantize them once and store them in a Const layer to be used everytime as they will not change.
47  */
48  TensorInfo constantInfo = constantLayer->GetOutputSlot(0).GetTensorInfo();
49  TensorInfo inputDequantizeInfo = dequantizeLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
50  TensorInfo outputDequantizeInfo = dequantizeLayer->GetOutputSlot(0).GetTensorInfo();
51 
52  bool requiresPermute = false;
53 
54  auto connection = dequantizeLayer->GetOutputSlot(0).GetConnection(0);
55  if (connection)
56  {
57  if (connection->GetOwningLayer().GetType() == LayerType::Convolution2d)
58  {
59  /**
60  * ArmNN does not currently support non-fixed weights or bias
61  * The NNAPI filter is always OHWI [depth_out, filter_height, filter_width, depth_in]
62  * but ArmNN expects the filter's height and width indices to match the input's height
63  * and width indices so we permute it to OIHW if the DataLayout is NCHW
64  */
65  ARMNN_LOG(info) << "ConvertConstDequantisationLayersToConstLayersImpl:: Connected to "
66  "Convolution layer.";
67  auto conv2dLayer = PolymorphicDowncast<Convolution2dLayer*>(&connection->GetOwningLayer());
68  if (conv2dLayer->GetParameters().m_DataLayout == DataLayout::NCHW)
69  {
70  ARMNN_LOG(info) << "ConvertConstDequantisationLayersToConstLayersImpl:: Connected to "
71  "Convolution layer and requires permute on weights. ";
72  requiresPermute = true;
73  }
74  }
75  }
76 
77  auto numConnections = constantLayer->GetOutputSlot(0).GetNumConnections();
78 
79  ARMNN_LOG(info) << "constantInfo datatype:" << armnn::GetDataTypeName(constantInfo.GetDataType())
80  << "inputDequantizeInfo datatype:" << armnn::GetDataTypeName(inputDequantizeInfo.GetDataType())
81  << "outputDequantizeInfo datatype:" << armnn::GetDataTypeName(outputDequantizeInfo.GetDataType());
82 
83  TensorInfo newInfo = inputDequantizeInfo;
84  newInfo.SetConstant(true);
85  if (requiresPermute)
86  {
87  ARMNN_LOG(info) << "TurboConvertConstDequantisationLayersToConstLayersImpl:: Permuting the constant data.";
88  const PermutationVector OHWIToOIHW = {0, 2, 3, 1};
89  // Here Permute weights
90  std::vector<Half> permutedValues(outputDequantizeInfo.GetNumElements());
91  armnnUtils::Permute(outputDequantizeInfo.GetShape(), OHWIToOIHW,
92  constantLayer->m_LayerOutput->Map(true), permutedValues.data(),
93  GetDataTypeSize(outputDequantizeInfo.GetDataType()));
94  ConstTensor newInput(newInfo, permutedValues);
95  constantLayer->m_LayerOutput.reset(new ScopedTensorHandle(newInput));
96  }
97  else
98  {
99  ConstTensor newInput(newInfo, constantLayer->m_LayerOutput->Map(true));
100  constantLayer->m_LayerOutput.reset(new ScopedTensorHandle(newInput));
101  }
102 
103  // Move connections in dequantize output to the constant layer.
104  // Dequantize layer will be removed if left unconnected.
105  dequantizeLayer->GetOutputSlot().MoveAllConnections(constantLayer->GetOutputSlot());
106 
107  // Update the output tensor
108  constantLayer->GetOutputSlot(0).SetTensorInfo(newInfo);
109  ARMNN_ASSERT(constantLayer->GetOutputSlot(0).GetTensorInfo().IsConstant() == true);
110 
111  // Set isConstant to true in all input tensor infos where constantLayer is now connected to
112  for (unsigned int i = numConnections; i < constantLayer->GetOutputSlot(0).GetNumConnections(); ++i)
113  {
114  auto info = constantLayer->GetOutputSlot(0).GetConnection(i)->GetOwningLayer().GetInputSlot(0)
116  info.SetConstant();
117  constantLayer->GetOutputSlot(0).GetConnection(i)->GetOwningLayer().GetInputSlot(0)
119  }
120  }
121 
122 };
123 
128 
129 } // namespace optimizations
130 } // namespace armnn
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
#define ARMNN_LOG(severity)
Definition: Logging.hpp:212
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:330
A layer that the constant data can be bound to.
std::shared_ptr< ConstTensorHandle > m_LayerOutput
This layer dequantizes the input tensor.
Layer & GetOwningLayer() const
Definition: Layer.hpp:53
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:339
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:286
const InputSlot * GetConnection(unsigned int index) const override
Definition: Layer.cpp:83
void MoveAllConnections(OutputSlot &destination)
Moves all connections to another OutputSlot.
Definition: Layer.cpp:156
unsigned int GetNumConnections() const override
Definition: Layer.hpp:158
Layer & GetOwningLayer() const
Definition: Layer.hpp:132
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:95
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:100
unsigned int GetNumElements() const
Definition: Tensor.hpp:198
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:518
bool IsConstant() const
Definition: Tensor.cpp:513
DataType GetDataType() const
Definition: Tensor.hpp:200
Copyright (c) 2021 ARM Limited and Contributors.
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:234
constexpr unsigned int GetDataTypeSize(DataType dataType)
Definition: TypesUtils.hpp:183
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:164