ArmNN
 25.11
Loading...
Searching...
No Matches
ArmComputeSubgraphUtils.hpp
Go to the documentation of this file.
1//
2// Copyright © 2020-2024 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
9
12
13namespace armnn
14{
15
16namespace
17{
18
19//
20// this helper only works if all layers where the inputs connect to are not selected
21//
22
23bool checkDataTypeInputandOutput(const Layer& layer)
24{
25 auto inputInfo = layer.GetInputSlot(0).GetTensorInfo();
26 auto outputInfo = layer.GetOutputSlot(0).GetTensorInfo();
27 bool sameDataType = (inputInfo.GetDataType() == outputInfo.GetDataType());
28
29 // Check is same quantization info (same scale and offset)
30 if (sameDataType)
31 {
32 if (IsQuantizedType(inputInfo.GetDataType()))
33 {
34 bool sameScale = (inputInfo.GetQuantizationScale() == outputInfo.GetQuantizationScale());
35 bool sameOffset = (inputInfo.GetQuantizationOffset() == outputInfo.GetQuantizationOffset());
36
37 return (sameScale && sameOffset);
38 }
39 else
40 {
41 return true;
42 }
43 }
44 else
45 {
46 return false;
47 }
48}
49
50} // namespace
51
52template<typename LayerType>
54 LayerType* baseLayer,
55 LayerType* replacementLayer,
56 ActivationLayer* activationLayer,
57 ActivationDescriptor& activationDesc)
58{
59 replacementLayer->SetAdditionalInfoForObject(
60 std::make_shared<ActivationDescriptor>(activationDesc));
61
62 SubgraphView substitutionSubgraph({baseLayer, activationLayer},
63 CreateIInputsFrom({baseLayer}),
64 CreateIOutputsFrom({activationLayer}));
65 SubgraphView replacementSubgraph(replacementLayer);
66
67 optimizationViews.AddSubstitution({substitutionSubgraph, replacementSubgraph});
68
69 return replacementLayer;
70}
71
72template<typename LayerType>
74 LayerType* baseLayer,
75 ActivationLayer* activationLayer,
76 ActivationDescriptor& activationDesc,
77 std::string name)
78{
80 IConnectableLayer* replacement = optimizationViews.GetINetwork()->AddAdditionLayer(name.c_str());
82 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
83
84 FuseLayer(optimizationViews,
85 baseLayer,
86 replacementLayer,
87 activationLayer,
88 activationDesc);
89
90 return replacementLayer;
91}
92
93template<typename LayerType>
95 LayerType* baseLayer,
96 ActivationLayer* activationLayer,
97 ActivationDescriptor& activationDesc,
98 std::string name)
99{
101 IConnectableLayer* replacement = optimizationViews.GetINetwork()->AddSubtractionLayer(name.c_str());
103 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
104
105 FuseLayer(optimizationViews,
106 baseLayer,
107 replacementLayer,
108 activationLayer,
109 activationDesc);
110
111 return replacementLayer;
112}
113
114template<typename LayerType>
116 LayerType* baseLayer,
117 ActivationLayer* activationLayer,
118 ActivationDescriptor& activationDesc,
119 std::string name)
120{
122 IConnectableLayer* replacement = optimizationViews.GetINetwork()->AddDivisionLayer(name.c_str());
124 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
125
126 FuseLayer(optimizationViews,
127 baseLayer,
128 replacementLayer,
129 activationLayer,
130 activationDesc);
131
132 return replacementLayer;
133}
134
135template<typename LayerType>
137 LayerType* baseLayer,
138 ActivationLayer* activationLayer,
139 ActivationDescriptor& activationDesc,
140 std::string name)
141{
143 IConnectableLayer* replacement = optimizationViews.GetINetwork()->AddMultiplicationLayer(name.c_str());
145 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
146
147 FuseLayer(optimizationViews,
148 baseLayer,
149 replacementLayer,
150 activationLayer,
151 activationDesc);
152
153 return replacementLayer;
154}
155
156template<typename LayerType>
158 LayerType* baseLayer,
159 ActivationLayer* activationLayer,
160 ActivationDescriptor& activationDesc,
161 BinaryOperation operation,
162 std::string name)
163{
164 IConnectableLayer* replacement = optimizationViews.GetINetwork()->AddElementwiseBinaryLayer(operation,
165 name.c_str());
166 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
167
168 FuseLayer(optimizationViews,
169 baseLayer,
170 replacementLayer,
171 activationLayer,
172 activationDesc);
173
174 return replacementLayer;
175}
176
177template<typename LayerType>
179 LayerType* baseLayer,
180 ActivationLayer* activationLayer,
181 ActivationDescriptor& activationDesc,
182 std::string name)
183{
184 IConnectableLayer* replacement =
185 optimizationViews.GetINetwork()->AddBatchNormalizationLayer(baseLayer->GetParameters(),
186 ConstTensor(),
187 ConstTensor(),
188 ConstTensor(),
189 ConstTensor(),
190 name.c_str());
191 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
192
193 FuseLayer(optimizationViews,
194 baseLayer,
195 replacementLayer,
196 activationLayer,
197 activationDesc);
198
199 SubgraphView substitutionSubgraph({baseLayer, activationLayer},
200 CreateIInputsFrom({baseLayer}),
201 CreateIOutputsFrom({activationLayer}));
202 SubgraphView replacementSubgraph(replacementLayer);
203
204 return replacementLayer;
205}
206
207template<typename LayerType>
209 LayerType* baseLayer,
210 ActivationLayer* activationLayer,
211 ActivationDescriptor& activationDesc,
212 std::string name)
213{
214 IConnectableLayer* replacement = optimizationViews.GetINetwork()
215 ->AddConvolution2dLayer(baseLayer->GetParameters(), name.c_str());
216
217 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
218
219
220 FuseLayer(optimizationViews,
221 baseLayer,
222 replacementLayer,
223 activationLayer,
224 activationDesc);
225
226 return replacementLayer;
227}
228
229template<typename LayerType>
231 LayerType* baseLayer,
232 ActivationLayer* activationLayer,
233 ActivationDescriptor& activationDesc,
234 std::string name)
235{
236 IConnectableLayer* replacement =
237 optimizationViews.GetINetwork()->AddDepthwiseConvolution2dLayer(baseLayer->GetParameters(), name.c_str());
238
239 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
240
241
242 FuseLayer(optimizationViews,
243 baseLayer,
244 replacementLayer,
245 activationLayer,
246 activationDesc);
247
248 return replacementLayer;
249}
250
251template<typename LayerType>
253 LayerType* baseLayer,
254 ActivationLayer* activationLayer,
255 ActivationDescriptor& activationDesc,
256 std::string name)
257{
258 IConnectableLayer* replacement =
259 optimizationViews.GetINetwork()->AddFullyConnectedLayer(baseLayer->GetParameters(),
260 name.c_str());
261 LayerType* replacementLayer = PolymorphicDowncast<LayerType*>(replacement);
262
263 FuseLayer(optimizationViews,
264 baseLayer,
265 replacementLayer,
266 activationLayer,
267 activationDesc);
268
269
270 return replacementLayer;
271}
272
273//
274// If reduce layer has multiple axes, add new layer for each axis to simulate the same behaviour
275// as currently only one axis is supported.
276//
277template<typename LayerType>
278std::vector<IConnectableLayer*> ChainReduceLayers(OptimizationViews& optimizationViews,
279 LayerType* baseLayer,
280 ReduceDescriptor& desc)
281{
282 // Vector of new chained layers, used for substitution.
283 std::vector<IConnectableLayer*> layers;
284
285 // Vector of axes so each layer is reshaped correctly.
286 std::vector<uint32_t> axes;
287 unsigned int recalulatedAxis = 0;
288
289 for (unsigned int i = 0; i != desc.m_vAxis.size(); ++i)
290 {
291 // Get TensorInfo from base layer and reduce shape using axis.
292 TensorInfo layerInfo = baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
293
294 axes.emplace_back(desc.m_vAxis[i]);
295
296 const TensorInfo& reducedTensorInfo = ComputeReductionTensorShape(layerInfo,
297 axes,
298 desc.m_KeepDims);
299
300 // Create a vector for the single axis to be assigned to the descriptor.
301 // Update axis if keepDims is set reduce layers correctly.
302 std::vector<uint32_t> singleAxis(1, desc.m_vAxis[i] - recalulatedAxis);
303
304 // Create a descriptor and assign single axis.
305 ReduceDescriptor newReduceDescriptor = baseLayer->GetParameters();
306 newReduceDescriptor.m_vAxis.assign(singleAxis.begin(), singleAxis.end());
307
308 // Add new layer to graph.
309 std::string layerName = "reduce_layer_" + std::to_string(i);
310
311 Layer* replacementLayer = PolymorphicDowncast<Layer*>(
312 optimizationViews.GetINetwork()->AddReduceLayer(newReduceDescriptor,
313 layerName.c_str()));
314
315 // Connect previous layer with new layer.
316 // The first and last layer will be connected when the subgraph is replaced.
317 if (!layers.empty())
318 {
319 layers[i - 1]->GetOutputSlot(0).Connect(replacementLayer->GetInputSlot(0));
320 }
321
322 // Set updated tensorInfo for new layer.
323 replacementLayer->GetOutputSlot(0).SetTensorInfo(reducedTensorInfo);
324
325 if (!desc.m_KeepDims)
326 {
327 recalulatedAxis++;
328 }
329
330 layers.emplace_back(replacementLayer);
331 }
332 return layers;
333}
334
335//
336// Substitute baseLayer with new subgraph
337//
338template<typename LayerType>
339void ReplaceLayers(OptimizationViews& optimizationViews,
340 LayerType* baseLayer,
341 std::vector<IConnectableLayer*>& layers)
342{
343 std::list<IConnectableLayer*> replacementLayers(layers.begin(), layers.end());
344
345 SubgraphView substitutionSubgraph(baseLayer);
346 SubgraphView replacementSubgraph(std::move(replacementLayers),
347 CreateIInputsFrom({replacementLayers.front()}),
348 CreateIOutputsFrom({replacementLayers.back()}));
349
350 optimizationViews.AddSubstitution({substitutionSubgraph, replacementSubgraph});
351}
352
353//
354// Substitute a multi-layer subgraph with one new layer
355//
356template<typename LayerType>
358 std::vector<IConnectableLayer*>& originalLayers,
359 LayerType* baseLayer,
360 const std::vector<SlotList> inputLayersSlotLists,
361 const std::vector<SlotList> outputLayersSlotLists)
362{
363 std::list<IConnectableLayer*> originalLayerList(originalLayers.begin(), originalLayers.end());
364
365 SubgraphView substitutionSubgraph(
366 std::move(originalLayerList),
367 CreateIInputsFromSlotLists<armnn::IConnectableLayer>(originalLayers, inputLayersSlotLists),
368 CreateIOutputsFromSlotLists<armnn::IConnectableLayer>(originalLayers, outputLayersSlotLists));
369 SubgraphView replacementSubgraph(baseLayer);
370
371 optimizationViews.AddSubstitution({substitutionSubgraph, replacementSubgraph});
372}
373
374} // namespace armnn
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
#define ARMNN_NO_DEPRECATE_WARN_END
This layer represents an activation operation with the specified activation function.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition Tensor.hpp:330
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition INetwork.hpp:81
IConnectableLayer * AddDivisionLayer(const char *name=nullptr)
Adds a division layer to the network.
Definition Network.cpp:508
IConnectableLayer * AddConvolution2dLayer(const Convolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D convolution layer to the network.
Definition Network.cpp:272
IConnectableLayer * AddAdditionLayer(const char *name=nullptr)
Adds an addition layer to the network.
Definition Network.cpp:409
IConnectableLayer * AddFullyConnectedLayer(const FullyConnectedDescriptor &fullyConnectedDescriptor, const char *name=nullptr)
Adds a fully connected layer to the network.
Definition Network.cpp:332
IConnectableLayer * AddBatchNormalizationLayer(const BatchNormalizationDescriptor &desc, const ConstTensor &mean, const ConstTensor &variance, const ConstTensor &beta, const ConstTensor &gamma, const char *name=nullptr)
Adds a batch normalization layer to the network.
Definition Network.cpp:423
IConnectableLayer * AddElementwiseBinaryLayer(const ElementwiseBinaryDescriptor &elementwiseBinaryDescriptor, const char *name=nullptr)
Add an ElementwiseBinary layer to the network.
Definition Network.cpp:314
IConnectableLayer * AddMultiplicationLayer(const char *name=nullptr)
Adds a multiplication layer to the network.
Definition Network.cpp:416
IConnectableLayer * AddDepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D depthwise convolution layer to the network.
Definition Network.cpp:292
IConnectableLayer * AddReduceLayer(const ReduceDescriptor &reduceDescriptor, const char *name=nullptr)
Adds a reduce layer to the network.
Definition Network.cpp:444
IConnectableLayer * AddSubtractionLayer(const char *name=nullptr)
Adds a subtraction layer to the network.
Definition Network.cpp:515
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
void AddSubstitution(SubstitutionPair &&substitution)
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition Layer.cpp:95
The SubgraphView class represents a subgraph of a Graph.
Copyright (c) 2021 ARM Limited and Contributors.
const TensorInfo ComputeReductionTensorShape(const armnn::TensorInfo &input, const std::vector< uint32_t > &vAxis, const bool keepDims)
Function to compute the output tensor shape based on the axes and if keepDims is set.
LayerType * FuseMultiplicationLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
void ReplaceMultipleLayers(OptimizationViews &optimizationViews, std::vector< IConnectableLayer * > &originalLayers, LayerType *baseLayer, const std::vector< SlotList > inputLayersSlotLists, const std::vector< SlotList > outputLayersSlotLists)
LayerType * FuseConvolution2dLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
LayerType * FuseAdditionLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
LayerType * FuseBatchNormalizationLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
constexpr bool IsQuantizedType()
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below.
Definition Types.hpp:494
LayerType * FuseLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, LayerType *replacementLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc)
std::vector< IConnectableLayer * > ChainReduceLayers(OptimizationViews &optimizationViews, LayerType *baseLayer, ReduceDescriptor &desc)
LayerType * FuseFullyConnectedLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
void ReplaceLayers(OptimizationViews &optimizationViews, LayerType *baseLayer, std::vector< IConnectableLayer * > &layers)
LayerType * FuseDivisionLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.
BinaryOperation
Definition Types.hpp:139
LayerType * FuseSubtractionLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
LayerType * FuseDepthwiseConvolution2dLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, std::string name)
LayerType * FuseElementwiseBinaryLayer(OptimizationViews &optimizationViews, LayerType *baseLayer, ActivationLayer *activationLayer, ActivationDescriptor &activationDesc, BinaryOperation operation, std::string name)
An ActivationDescriptor for the ActivationLayer.
A ReduceDescriptor for the REDUCE operators.
bool m_KeepDims
if true then output shape has no change.
std::vector< uint32_t > m_vAxis
The indices of the dimensions to reduce.