ArmNN
 24.02
PermuteAndBatchToSpaceAsDepthToSpace.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019-2020,2023 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "Optimization.hpp"
8 
9 namespace armnn
10 {
11 namespace optimizations
12 {
13 
14 /// Replaces Permute leading into BatchToSpace with a DepthToSpace
15 /// in the case where the Permute swaps the batch and channels dimensions
16 /// such that the replacement is valid.
17 template <typename PermuteType>
19 {
20 public:
21  void Run(Graph& graph, InputSlot& connection) const
22  {
23  // Validate base layer (the Permute) is compatible
24  Layer& base = connection.GetConnectedOutputSlot()->GetOwningLayer();
26  const TensorInfo& inputInfo = base.GetInputSlot(0).GetTensorInfo();
27  const TensorInfo& intermediateInfo = base.GetOutputSlot(0).GetTensorInfo();
28  if (intermediateInfo.GetNumDimensions() != 4)
29  {
30  // Must be 4D, otherwise the below checks do not make sense
31  return;
32  }
33  if (!static_cast<PermuteType&>(base).GetParameters().m_DimMappings.IsEqual(PermutationVector{ 3, 1, 2, 0 }))
34  {
35  // Must swap batch and channels dimensions, otherwise it is not the (original) channels dimension
36  // that is being decomposed.
37  return;
38  }
39 
40  // Validate child layer (the BatchToSpace) is compatible
41  Layer& child = connection.GetOwningLayer();
43  const TensorInfo& outputInfo = child.GetOutputSlot(0).GetTensorInfo();
44  const BatchToSpaceNdDescriptor& batchToSpaceDesc = static_cast<BatchToSpaceNdLayer&>(child).GetParameters();
45  if (batchToSpaceDesc.m_DataLayout != DataLayout::NHWC)
46  {
47  // The rest of this function assumes NHWC, although in future this restriction could be lifted.
48  return;
49  }
50  if (batchToSpaceDesc.m_Crops != std::vector<std::pair<unsigned int, unsigned int>>{ { 0, 0 }, { 0, 0 } })
51  {
52  // Cropping is not supported in DepthToSpace
53  return;
54  }
55  if (batchToSpaceDesc.m_BlockShape.size() != 2 ||
56  batchToSpaceDesc.m_BlockShape[0] != batchToSpaceDesc.m_BlockShape[1])
57  {
58  // Asymmetric or non-2D block sizes are not supported by DepthToSpace
59  return;
60  }
61  uint32_t blockSize = batchToSpaceDesc.m_BlockShape[0];
62  if (outputInfo.GetShape()[0] != 1 || outputInfo.GetShape()[3] != 1)
63  {
64  // The final output must have 1 batch and 1 channel because these dimensions will be swapped around
65  // once we make the substitution, and it needs to be equivalent.
66  return;
67  }
68 
69  // Validate the intermediate tensor quantization params.
70  // These must be identical to either the input or output quantization params, otherwise the intermediate tensor
71  // may not have sufficient range/precision to preserve the values.
72  // This would mean that once we perform the substitution this loss of precision will no longer occur,
73  // so we would have changed the meaning of the network.
74  bool isIntermediateQuantParamsSameAsInput =
75  intermediateInfo.GetQuantizationScale() == inputInfo.GetQuantizationScale() &&
76  intermediateInfo.GetQuantizationOffset() == inputInfo.GetQuantizationOffset();
77  bool isIntermediateQuantParamsSameAsOutput =
78  intermediateInfo.GetQuantizationScale() == outputInfo.GetQuantizationScale() &&
79  intermediateInfo.GetQuantizationOffset() == outputInfo.GetQuantizationOffset();
80  if (!isIntermediateQuantParamsSameAsInput && !isIntermediateQuantParamsSameAsOutput)
81  {
82  return;
83  }
84 
85  // Insert equivalent DepthToSpace layer
86  const std::string name = std::string("merged-") + base.GetName() + std::string("-with-") + child.GetName();
87 
88  // Inserts equivalent reshape before base layer.
89  const DepthToSpaceDescriptor depthToSpaceDesc(blockSize, DataLayout::NHWC);
90  auto& depthToSpace = *graph.InsertNewLayer<DepthToSpaceLayer>(base.GetInputSlot(0),
91  depthToSpaceDesc,
92  name.c_str());
93 
94  // Moves connections from child output to new layer.
95  // Child layer will be removed as it's left unconnected.
96  // Base layer will be removed if left unconnected.
97  child.GetOutputSlot().MoveAllConnections(depthToSpace.GetOutputSlot());
98  }
99 };
100 
101 using PermuteAndBatchToSpaceAsDepthToSpace = OptimizeForConnection<PermuteLayer, BatchToSpaceNdLayer,
105 } // namespace optimizations
106 } // namespace armnn
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::DepthToSpaceDescriptor
SpaceToDepthDescriptor DepthToSpaceDescriptor
A DepthToSpaceDescriptor for the DepthToSpaceLayer.
Definition: Descriptors.hpp:1099
armnn::LayerType::Permute
@ Permute
armnn::InputSlot::GetOwningLayer
Layer & GetOwningLayer() const
Definition: Layer.hpp:53
armnn::OutputSlot::GetTensorInfo
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:92
armnn::DataLayout::NHWC
@ NHWC
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::LayerType::Transpose
@ Transpose
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
armnn::optimizations::PermuteAndBatchToSpaceAsDepthToSpaceImpl::Run
void Run(Graph &graph, InputSlot &connection) const
Definition: PermuteAndBatchToSpaceAsDepthToSpace.hpp:21
armnn::optimizations::PermuteAndBatchToSpaceAsDepthToSpace
OptimizeForConnection< PermuteLayer, BatchToSpaceNdLayer, PermuteAndBatchToSpaceAsDepthToSpaceImpl< PermuteLayer > > PermuteAndBatchToSpaceAsDepthToSpace
Definition: PermuteAndBatchToSpaceAsDepthToSpace.hpp:102
armnn::BatchToSpaceNdDescriptor::m_Crops
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
Definition: Descriptors.hpp:900
armnn::BatchToSpaceNdLayer
This layer represents a BatchToSpaceNd operation.
Definition: BatchToSpaceNdLayer.hpp:13
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::Layer::GetName
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:332
armnn::Layer
Definition: Layer.hpp:230
armnn::InputSlot::GetTensorInfo
const TensorInfo & GetTensorInfo() const override
Gets the TensorInfo for this InputSlot.
Definition: Layer.cpp:592
armnn::TransposeLayer
This layer represents a transpose operation.
Definition: TransposeLayer.hpp:15
armnn::OutputSlot::GetOwningLayer
Layer & GetOwningLayer() const
Definition: Layer.hpp:132
armnn::OptimizeForConnection
Definition: Optimization.hpp:118
armnn::optimizations::PermuteAndBatchToSpaceAsDepthToSpaceImpl
Replaces Permute leading into BatchToSpace with a DepthToSpace in the case where the Permute swaps th...
Definition: PermuteAndBatchToSpaceAsDepthToSpace.hpp:18
armnn::PermutationVector
Definition: Types.hpp:314
armnn::InputSlot
Definition: Layer.hpp:42
armnn::BatchToSpaceNdDescriptor
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
Definition: Descriptors.hpp:875
armnn::LayerType::BatchToSpaceNd
@ BatchToSpaceNd
armnn::Layer::GetType
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:286
armnn::InputSlot::GetConnectedOutputSlot
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::BatchToSpaceNdDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:902
armnn::Graph
Definition: Graph.hpp:30