ArmNN
 25.11
Loading...
Searching...
No Matches
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>
12
13namespace armnn
14{
15namespace optimizations
16{
17
19{
20public:
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),
31 }
32 }
33protected:
36private:
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 InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition Layer.hpp:337
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition Layer.hpp:339
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
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition Layer.cpp:95
Layer & GetOwningLayer() const
Definition Layer.hpp:132
const TensorInfo & GetTensorInfo() const override
Definition Layer.cpp:100
const TensorShape & GetShape() const
Definition Tensor.hpp:193
unsigned int GetNumElements() const
Definition Tensor.hpp:198
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
OptimizeForConnection< ConstantLayer, DequantizeLayer, TurboConvertConstDequantisationLayersToConstLayersImpl > TurboConvertConstDequantisationLayersToConstLayers
Copyright (c) 2021 ARM Limited and Contributors.
constexpr const char * GetDataTypeName(DataType dataType)
constexpr unsigned int GetDataTypeSize(DataType dataType)
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.