ArmNN
 25.11
Loading...
Searching...
No Matches
AddBroadcastReshapeLayer.hpp
Go to the documentation of this file.
1//
2// Copyright © 2020-2021,2023-2025 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#pragma once
6
7#include "Optimization.hpp"
8
11
12namespace armnn
13{
15{
16
17static const std::set<armnn::LayerType> broadcastOps{ LayerType::Addition, LayerType::Division,
22
24{
25public:
26 /// Run for every ElementwiseBaseLayer. Add Broadcast reshape layer if the inputs shape are different.
27 void Run(Graph& graph, Layer& layer) const
28 {
29 if (std::find(broadcastOps.begin(), broadcastOps.end(), layer.GetType()) != broadcastOps.end())
30 {
33
34 const TensorInfo& inputInfo0 = layer.GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo();
35 const TensorInfo& inputInfo1 = layer.GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo();
36
37 if (inputInfo0.GetNumDimensions() == inputInfo1.GetNumDimensions())
38 {
39 return;
40 }
41
42 unsigned int reshapeSlot = 1;
43 TensorInfo reshapeInfo = inputInfo1;
44 TensorInfo inputInfo = inputInfo0;
45
46 if (inputInfo0.GetNumDimensions() < inputInfo1.GetNumDimensions())
47 {
48 reshapeSlot = 0;
49 reshapeInfo = inputInfo0;
50 inputInfo = inputInfo1;
51 }
52
53 uint32_t numDimensions = inputInfo.GetNumDimensions();
54
55 std::vector<unsigned> reshapedDim;
56 for (unsigned int i = 0; i < reshapeInfo.GetNumDimensions(); ++i)
57 {
58 reshapedDim.push_back(reshapeInfo.GetShape()[i]);
59 }
60
61 std::vector<unsigned int> reshapedDimensions(numDimensions, 1);
62 std::copy_backward(reshapedDim.begin(), reshapedDim.end(), reshapedDimensions.end());
63
64 reshapeInfo.SetShape(armnn::TensorShape{ numDimensions, reshapedDimensions.data() });
65
66 // If the parent layer is a Constant layer and it is only used once or trying to reshape to 4D
67 // we can short circuit by just changing the tensor info rather than adding a reshape layer.
68
69 bool elementWiseMul = false;
71 {
72 auto& binaryLayerOp = *PolymorphicDowncast<ElementwiseBinaryLayer*>(&layer);
73 elementWiseMul = binaryLayerOp.GetParameters().m_Operation==BinaryOperation::Mul;
74 }
75 auto parentName = std::string(layer.GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer().GetName());
76 Layer& parentLayer = layer.GetInputSlot(reshapeSlot).GetConnectedOutputSlot()->GetOwningLayer();
77 if ((parentLayer.GetType() == armnn::LayerType::Constant) &&
78 ((parentLayer.GetOutputSlot(0).GetNumConnections() == 1) ||
79 (parentName.find("Quantize")!=std::string::npos && elementWiseMul)))
80 {
81 ConstantLayer& constantLayer = static_cast<ConstantLayer&>(parentLayer);
82
83 constantLayer.m_LayerOutput = std::make_unique<ScopedTensorHandle>(
84 ConstTensor(reshapeInfo, constantLayer.m_LayerOutput.get()->GetConstTensor<void>()));
85 constantLayer.GetOutputSlot().SetTensorInfo(reshapeInfo);
86 }
87 else
88 {
89 const std::string layerName = "Reshape_for:" + layer.GetNameStr() + "-" + std::to_string(reshapeSlot);
90 const ReshapeDescriptor descriptor{ reshapeInfo.GetShape() };
91 ReshapeLayer* reshapeLayer =
92 graph.InsertNewLayer<ReshapeLayer>(layer.GetInputSlot(reshapeSlot), descriptor, layerName.c_str());
93 reshapeLayer->GetOutputSlot().SetTensorInfo(reshapeInfo);
94 }
95 }
96 }
97
98protected:
101};
102
104
105} // namespace optimizations
106} // namespace armnn
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
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
Definition Graph.hpp:481
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 std::string & GetNameStr() const
Definition Layer.hpp:240
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition Layer.hpp:339
const char * GetName() const override
Returns the name of the layer.
Definition Layer.hpp:332
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition Layer.hpp:286
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
bool IsTensorInfoSet() const override
Definition Layer.cpp:105
const TensorInfo & GetTensorInfo() const override
Definition Layer.cpp:100
This layer represents a reshape operation.
const TensorShape & GetShape() const
Definition Tensor.hpp:193
unsigned int GetNumDimensions() const
Definition Tensor.hpp:197
void SetShape(const TensorShape &newShape)
Definition Tensor.hpp:195
void Run(Graph &graph, Layer &layer) const
Run for every ElementwiseBaseLayer. Add Broadcast reshape layer if the inputs shape are different.
OptimizeForType< Layer, AddBroadcastReshapeLayerImpl > AddBroadcastReshapeLayer
Copyright (c) 2021 ARM Limited and Contributors.
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.
A ReshapeDescriptor for the ReshapeLayer.