ArmNN
 24.08
AddBroadcastReshapeLayer.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2020-2021,2023-2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "Optimization.hpp"
8 
11 
12 namespace armnn
13 {
14 namespace optimizations
15 {
16 
17 static const std::set<armnn::LayerType> broadcastOps{ LayerType::Addition, LayerType::Division,
22 
24 {
25 public:
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 we can short circuit by just
67  // changing the tensor info rather than adding a reshape layer.
68  Layer& parentLayer = layer.GetInputSlot(reshapeSlot).GetConnectedOutputSlot()->GetOwningLayer();
69  if ((parentLayer.GetType() == armnn::LayerType::Constant) &&
70  (parentLayer.GetOutputSlot(0).GetNumConnections() == 1))
71  {
72  ConstantLayer& constantLayer = static_cast<ConstantLayer&>(parentLayer);
73 
74  constantLayer.m_LayerOutput = std::make_unique<ScopedTensorHandle>(
75  ConstTensor(reshapeInfo, constantLayer.m_LayerOutput.get()->GetConstTensor<void>()));
76  constantLayer.GetOutputSlot().SetTensorInfo(reshapeInfo);
77  }
78  else
79  {
80  const std::string layerName = "Reshape_for:" + layer.GetNameStr() + "-" + std::to_string(reshapeSlot);
81  const ReshapeDescriptor descriptor{ reshapeInfo.GetShape() };
82  ReshapeLayer* reshapeLayer =
83  graph.InsertNewLayer<ReshapeLayer>(layer.GetInputSlot(reshapeSlot), descriptor, layerName.c_str());
84  reshapeLayer->GetOutputSlot().SetTensorInfo(reshapeInfo);
85  }
86  }
87  }
88 
89 protected:
90  AddBroadcastReshapeLayerImpl() = default;
92 };
93 
95 
96 } // namespace optimizations
97 } // namespace armnn
armnn::OutputSlot::GetTensorInfo
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:100
armnn::OutputSlot::SetTensorInfo
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:95
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::LayerType::Comparison
@ Comparison
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:197
armnn::Layer::GetOutputSlot
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:339
Optimization.hpp
armnn::Layer::GetInputSlot
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
armnn::OutputSlot::IsTensorInfoSet
bool IsTensorInfoSet() const override
Definition: Layer.cpp:105
armnn::LayerType::ElementwiseBinary
@ ElementwiseBinary
armnn::Layer
Definition: Layer.hpp:230
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::OutputSlot::GetOwningLayer
Layer & GetOwningLayer() const
Definition: Layer.hpp:132
armnn::ReshapeLayer
This layer represents a reshape operation.
Definition: ReshapeLayer.hpp:15
armnn::LayerType::Subtraction
@ Subtraction
armnn::LayerType::Prelu
@ Prelu
armnn::LayerType::LogicalBinary
@ LogicalBinary
armnn::OutputSlot::GetNumConnections
unsigned int GetNumConnections() const override
Definition: Layer.hpp:158
PolymorphicDowncast.hpp
armnn::ReshapeDescriptor
A ReshapeDescriptor for the ReshapeLayer.
Definition: Descriptors.hpp:1023
armnn::optimizations::AddBroadcastReshapeLayerImpl::AddBroadcastReshapeLayerImpl
AddBroadcastReshapeLayerImpl()=default
armnn::optimizations::AddBroadcastReshapeLayerImpl::~AddBroadcastReshapeLayerImpl
~AddBroadcastReshapeLayerImpl()=default
armnn::LayerType::Multiplication
@ Multiplication
armnn::LayerType::Addition
@ Addition
armnn::Layer::GetNameStr
const std::string & GetNameStr() const
Definition: Layer.hpp:240
armnn::LayerType::Division
@ Division
armnn::OptimizeForType
Definition: Optimization.hpp:67
armnn::Layer::GetType
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:286
TensorHandle.hpp
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
armnn::ConstantLayer::m_LayerOutput
std::shared_ptr< ConstTensorHandle > m_LayerOutput
Definition: ConstantLayer.hpp:46
armnn::LayerType::Minimum
@ Minimum
armnn::InputSlot::GetConnectedOutputSlot
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
armnn::ConstantLayer
A layer that the constant data can be bound to.
Definition: ConstantLayer.hpp:15
armnn::TensorInfo::SetShape
void SetShape(const TensorShape &newShape)
Definition: Tensor.hpp:195
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::ConstTensor
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:329
armnn::optimizations::AddBroadcastReshapeLayerImpl::Run
void Run(Graph &graph, Layer &layer) const
Run for every ElementwiseBaseLayer. Add Broadcast reshape layer if the inputs shape are different.
Definition: AddBroadcastReshapeLayer.hpp:27
armnn::LayerType::Maximum
@ Maximum
armnn::optimizations::AddBroadcastReshapeLayerImpl
Definition: AddBroadcastReshapeLayer.hpp:23
armnn::Graph
Definition: Graph.hpp:30
armnn::Graph::InsertNewLayer
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
armnn::LayerType::Constant
@ Constant