ArmNN  NotReleased
PermuteAndBatchToSpaceAsDepthToSpaceImpl Class Reference

#include <PermuteAndBatchToSpaceAsDepthToSpace.hpp>

Public Member Functions

void Run (Graph &graph, InputSlot &connection) const
 

Detailed Description

Replaces Permute leading into BatchToSpace with a DepthToSpace in the case where the Permute swaps the batch and channels dimensions such that the replacement is valid.

Definition at line 17 of file PermuteAndBatchToSpaceAsDepthToSpace.hpp.

Member Function Documentation

◆ Run()

void Run ( Graph graph,
InputSlot connection 
) const

Definition at line 11 of file PermuteAndBatchToSpaceAsDepthToSpace.cpp.

References armnn::BatchToSpaceNd, InputSlot::GetConnectedOutputSlot(), InputSlot::GetConnection(), Layer::GetInputSlot(), Layer::GetName(), TensorInfo::GetNumDimensions(), Layer::GetOutputHandler(), Layer::GetOutputSlot(), InputSlot::GetOwningLayer(), OutputSlot::GetOwningLayer(), IOutputSlot::GetTensorInfo(), OutputSlot::GetTensorInfo(), Layer::GetType(), BatchToSpaceNdDescriptor::m_Crops, BatchToSpaceNdDescriptor::m_DataLayout, armnn::NHWC, armnn::Permute, and OutputHandler::SetTensorInfo().

12 {
13  // Validate base layer (the Permute) is compatible
14  Layer& base = connection.GetConnectedOutputSlot()->GetOwningLayer();
15  BOOST_ASSERT(base.GetType() == LayerType::Permute);
16  const TensorInfo& inputInfo = base.GetInputSlot(0).GetConnection()->GetTensorInfo();
17  const TensorInfo& intermediateInfo = base.GetOutputSlot(0).GetTensorInfo();
18  if (intermediateInfo.GetNumDimensions() != 4)
19  {
20  // Must be 4D, otherwise the below checks do not make sense
21  return;
22  }
23  if (!static_cast<PermuteLayer&>(base).GetParameters().m_DimMappings.IsEqual(PermutationVector{ 3, 1, 2, 0 }))
24  {
25  // Must swap batch and channels dimensions, otherwise it is not the (original) channels dimension
26  // that is being decomposed.
27  return;
28  }
29 
30  // Validate child layer (the BatchToSpace) is compatible
31  Layer& child = connection.GetOwningLayer();
32  BOOST_ASSERT(child.GetType() == LayerType::BatchToSpaceNd);
33  const TensorInfo& outputInfo = child.GetOutputSlot(0).GetTensorInfo();
34  const BatchToSpaceNdDescriptor& batchToSpaceDesc = static_cast<BatchToSpaceNdLayer&>(child).GetParameters();
35  if (batchToSpaceDesc.m_DataLayout != DataLayout::NHWC)
36  {
37  // The rest of this function assumes NHWC, although in future this restriction could be lifted.
38  return;
39  }
40  if (batchToSpaceDesc.m_Crops != std::vector<std::pair<unsigned int, unsigned int>>{ { 0, 0 }, { 0, 0 } })
41  {
42  // Cropping is not supported in DepthToSpace
43  return;
44  }
45  if (batchToSpaceDesc.m_BlockShape.size() != 2 ||
46  batchToSpaceDesc.m_BlockShape[0] != batchToSpaceDesc.m_BlockShape[1])
47  {
48  // Asymmetric or non-2D block sizes are not supported by DepthToSpace
49  return;
50  }
51  uint32_t blockSize = batchToSpaceDesc.m_BlockShape[0];
52  if (outputInfo.GetShape()[0] != 1 || outputInfo.GetShape()[3] != 1)
53  {
54  // The final output must have 1 batch and 1 channel because these dimensions will be swapped around
55  // once we make the substitution, and it needs to be equivalent.
56  return;
57  }
58 
59  // Validate the intermediate tensor quantization params.
60  // These must be identical to either the input or output quantization params, otherwise the intermediate tensor
61  // may not have sufficient range/precision to preserve the values.
62  // This would mean that once we perform the substitution this loss of precision will no longer occur,
63  // so we would have changed the meaning of the network.
64  bool isIntermediateQuantParamsSameAsInput =
65  intermediateInfo.GetQuantizationScale() == inputInfo.GetQuantizationScale() &&
66  intermediateInfo.GetQuantizationOffset() == inputInfo.GetQuantizationOffset();
67  bool isIntermediateQuantParamsSameAsOutput =
68  intermediateInfo.GetQuantizationScale() == outputInfo.GetQuantizationScale() &&
69  intermediateInfo.GetQuantizationOffset() == outputInfo.GetQuantizationOffset();
70  if (!isIntermediateQuantParamsSameAsInput && !isIntermediateQuantParamsSameAsOutput)
71  {
72  return;
73  }
74 
75  // Insert equivalent DepthToSpace layer
76  const std::string name = std::string("merged-") + base.GetName() + std::string("-with-") + child.GetName();
77 
78  // Inserts equivalent reshape before base layer.
79  const DepthToSpaceDescriptor depthToSpaceDesc(blockSize, DataLayout::NHWC);
80  auto& depthToSpace = *graph.InsertNewLayer<DepthToSpaceLayer>(base.GetInputSlot(0), depthToSpaceDesc, name.c_str());
81  depthToSpace.GetOutputHandler().SetTensorInfo(outputInfo);
82 
83  // Moves connections from child output to new layer.
84  // Child layer will be removed as it's left unconnected.
85  // Base layer will be removed if left unconnected.
86  child.GetOutputSlot().MoveAllConnections(depthToSpace.GetOutputSlot());
87 }
const OutputHandler & GetOutputHandler(unsigned int i=0) const
Definition: Layer.hpp:221
This layer represents a DepthToSpace operation.
This layer represents a BatchToSpaceNd operation.
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:55
LayerType GetType() const
Definition: Layer.hpp:259
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:264
const char * GetName() const override
Definition: Layer.hpp:305
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
virtual const TensorInfo & GetTensorInfo() const =0
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:92
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
const IOutputSlot * GetConnection() const override
Definition: Layer.hpp:199
void MoveAllConnections(OutputSlot &destination)
Moves all connections to another OutputSlot.
Definition: Layer.cpp:112
void SetTensorInfo(const TensorInfo &tensorInfo)
Sets the TensorInfo used by this output handler.
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Definition: Graph.hpp:409
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63
Layer & GetOwningLayer() const
Definition: Layer.hpp:115
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Definition: Layer.hpp:312
Layer & GetOwningLayer() const
Definition: Layer.hpp:52
std::vector< unsigned int > m_BlockShape
Block shape values.
float GetQuantizationScale() const
Definition: Tensor.cpp:247
const InputSlot & GetInputSlot(unsigned int index) const override
Definition: Layer.hpp:310

The documentation for this class was generated from the following files: