ArmNN
 22.05
armnn::optimizations::pad_fold Namespace Reference

Classes

class  FoldPadIntoConvolution2dImpl
 
class  FoldPadIntoDepthwiseConvolution2dImpl
 
class  FoldPadIntoPooling2dImpl
 

Functions

float GetZeroElement (const TensorInfo &tensorInfo)
 
float GetLowestElement (const TensorInfo &tensorInfo)
 
bool IsNeutralElement (const Convolution2dDescriptor &, const TensorInfo &tensorInfo, const float tensorValue)
 
bool IsNeutralElement (const DepthwiseConvolution2dDescriptor &, const TensorInfo &tensorInfo, const float tensorValue)
 
bool IsNeutralElement (const Pooling2dDescriptor &descriptor, const TensorInfo &tensorInfo, const float tensorValue)
 
template<typename Descriptor >
bool TryFoldPadIntoLayer2d (const PadDescriptor &padDescriptor, Descriptor &layerDescriptor, const TensorInfo &tensorInfo)
 
bool TryFoldPadIntoLayer2d (const PadDescriptor &padDescriptor, Pooling2dDescriptor &poolDescriptor, const TensorInfo &tensorInfo)
 
template<typename Layer2dT >
Layer2dT * FoldPadIntoLayer2dImpl (Graph &graph, InputSlot &connection)
 

Function Documentation

◆ FoldPadIntoLayer2dImpl()

Layer2dT* armnn::optimizations::pad_fold::FoldPadIntoLayer2dImpl ( Graph graph,
InputSlot connection 
)

Definition at line 129 of file FoldPadIntoLayer2d.hpp.

References OutputSlot::Connect(), armnn::Constant, OutputSlot::Disconnect(), InputSlot::GetConnectedOutputSlot(), Layer::GetInputSlot(), Layer::GetName(), Layer::GetOutputSlot(), InputSlot::GetOwningLayer(), OutputSlot::GetOwningLayer(), LayerWithParameters< Parameters >::GetParameters(), OutputSlot::GetTensorInfo(), Layer::GetType(), Graph::InsertNewLayer(), and TryFoldPadIntoLayer2d().

130 {
131  PadLayer& padLayer = *PolymorphicDowncast<PadLayer*>(&connection.GetConnectedOutputSlot()->GetOwningLayer());
132  Layer2dT& layer2d = *PolymorphicDowncast<Layer2dT*>(&connection.GetOwningLayer());
133 
134  const PadDescriptor& padDescriptor = padLayer.GetParameters();
135  auto newLayer2dDescriptor = layer2d.GetParameters();
136 
137  if (!TryFoldPadIntoLayer2d(padDescriptor, newLayer2dDescriptor, padLayer.GetOutputSlot().GetTensorInfo()))
138  {
139  return nullptr;
140  }
141 
142  // Save original parent output slot of the pad layer
143  OutputSlot& parentSlot = *padLayer.GetInputSlot(0).GetConnectedOutputSlot();
144 
145  // Insert new layer2d layer between the pad layer an its parent layer.
146  const std::string name = std::string("folded-") + padLayer.GetName() + "-into-" + layer2d.GetName();
147  auto& newLayer2d = *graph.InsertNewLayer<Layer2dT>(padLayer.GetInputSlot(0), newLayer2dDescriptor, name.c_str());
148 
149  newLayer2d.GetOutputSlot().MoveAllConnections(parentSlot);
150  // Start at 1 to connect only weights and bias
151  for (unsigned int i = 1; i < layer2d.GetNumInputSlots(); ++i)
152  {
153  if (layer2d.GetInputSlot(i).GetConnectedOutputSlot() != nullptr)
154  {
155  Layer& tgtLayer = layer2d.GetInputSlot(i).GetConnectedOutputSlot()->GetOwningLayer();
156  // Ensure we are definitely connecting the necessary constant layers
157  if (tgtLayer.GetType() == armnn::LayerType::Constant)
158  {
159  // Remove old connection and connect to new layer2d
160  tgtLayer.GetOutputSlot(0).Disconnect(layer2d.GetInputSlot(i));
161  tgtLayer.GetOutputSlot(0).Connect(newLayer2d.GetInputSlot(i));
162  }
163  }
164  }
165 
166  // Moves connections in old layer2d layer output to new layer.
167  // Old layer2d layer will be removed as it's left unconnected.
168  // Pad layer will be removed if left unconnected.
169  layer2d.GetOutputSlot().MoveAllConnections(newLayer2d.GetOutputSlot());
170 
171  return &newLayer2d;
172 }
bool TryFoldPadIntoLayer2d(const PadDescriptor &padDescriptor, Pooling2dDescriptor &poolDescriptor, const TensorInfo &tensorInfo)

◆ GetLowestElement()

float armnn::optimizations::pad_fold::GetLowestElement ( const TensorInfo tensorInfo)
inline

Definition at line 26 of file FoldPadIntoLayer2d.hpp.

References ARMNN_ASSERT_MSG, armnn::BFloat16, armnn::Float16, armnn::Float32, TensorInfo::GetDataType(), TensorInfo::GetQuantizationOffset(), TensorInfo::GetQuantizationScale(), armnn::QAsymmS8, armnn::QAsymmU8, armnn::QSymmS16, and armnn::QSymmS8.

Referenced by IsNeutralElement().

27 {
28  constexpr float negativeInfinity = -std::numeric_limits<float>::infinity();
29  const float scale = tensorInfo.GetQuantizationScale();
30  const int32_t offset = tensorInfo.GetQuantizationOffset();
31 
32  switch (tensorInfo.GetDataType())
33  {
34  case DataType::Float16:
35  return armnnUtils::SelectiveQuantize<armnn::Half>(negativeInfinity, scale, offset);
36  case DataType::Float32:
37  return armnnUtils::SelectiveQuantize<float>(negativeInfinity, scale, offset);
38  case DataType::QAsymmU8:
39  return armnnUtils::SelectiveQuantize<uint8_t>(negativeInfinity, scale, offset);
40  case DataType::QSymmS16:
41  return armnnUtils::SelectiveQuantize<int16_t>(negativeInfinity, scale, offset);
42  case DataType::QSymmS8:
43  // Fall-through
44  case DataType::QAsymmS8:
45  return armnnUtils::SelectiveQuantize<int8_t>(negativeInfinity, scale, offset);
46  case DataType::BFloat16:
47  return armnnUtils::SelectiveQuantize<armnn::BFloat16>(negativeInfinity, scale, offset);
48  default:
49  {
50  ARMNN_ASSERT_MSG(false, "Unsupported DataType");
51  return NAN;
52  }
53  }
54 }
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15

◆ GetZeroElement()

float armnn::optimizations::pad_fold::GetZeroElement ( const TensorInfo tensorInfo)
inline

Definition at line 21 of file FoldPadIntoLayer2d.hpp.

References TensorInfo::GetQuantizationOffset(), and TensorInfo::IsQuantized().

Referenced by IsNeutralElement().

22 {
23  return static_cast<float>(tensorInfo.IsQuantized() ? tensorInfo.GetQuantizationOffset() : 0);
24 }

◆ IsNeutralElement() [1/3]

bool armnn::optimizations::pad_fold::IsNeutralElement ( const Convolution2dDescriptor ,
const TensorInfo tensorInfo,
const float  tensorValue 
)
inline

Definition at line 56 of file FoldPadIntoLayer2d.hpp.

References GetZeroElement().

Referenced by TryFoldPadIntoLayer2d().

57 {
58  return tensorValue == GetZeroElement(tensorInfo);
59 }
float GetZeroElement(const TensorInfo &tensorInfo)

◆ IsNeutralElement() [2/3]

bool armnn::optimizations::pad_fold::IsNeutralElement ( const DepthwiseConvolution2dDescriptor ,
const TensorInfo tensorInfo,
const float  tensorValue 
)
inline

Definition at line 61 of file FoldPadIntoLayer2d.hpp.

References GetZeroElement().

64 {
65  return tensorValue == GetZeroElement(tensorInfo);
66 }
float GetZeroElement(const TensorInfo &tensorInfo)

◆ IsNeutralElement() [3/3]

bool armnn::optimizations::pad_fold::IsNeutralElement ( const Pooling2dDescriptor descriptor,
const TensorInfo tensorInfo,
const float  tensorValue 
)
inline

Definition at line 68 of file FoldPadIntoLayer2d.hpp.

References GetLowestElement(), GetZeroElement(), Pooling2dDescriptor::m_PoolType, and armnn::Max.

70 {
71  return (descriptor.m_PoolType == PoolingAlgorithm::Max)
72  ? tensorValue <= GetLowestElement(tensorInfo)
73  : tensorValue == GetZeroElement(tensorInfo);
74 }
float GetZeroElement(const TensorInfo &tensorInfo)
float GetLowestElement(const TensorInfo &tensorInfo)

◆ TryFoldPadIntoLayer2d() [1/2]

bool armnn::optimizations::pad_fold::TryFoldPadIntoLayer2d ( const PadDescriptor padDescriptor,
Descriptor &  layerDescriptor,
const TensorInfo tensorInfo 
)

Definition at line 77 of file FoldPadIntoLayer2d.hpp.

References DataLayoutIndexed::GetChannelsIndex(), DataLayoutIndexed::GetHeightIndex(), DataLayoutIndexed::GetWidthIndex(), IsNeutralElement(), PadDescriptor::m_PadList, and PadDescriptor::m_PadValue.

Referenced by FoldPadIntoLayer2dImpl().

79 {
80  armnnUtils::DataLayoutIndexed layout = armnnUtils::DataLayoutIndexed(layerDescriptor.m_DataLayout);
81  constexpr unsigned int batchIndex = 0;
82 
83  constexpr auto noPad = std::make_pair(0U, 0U);
84 
85  if ((!IsNeutralElement(layerDescriptor, tensorInfo, padDescriptor.m_PadValue)) ||
86  (padDescriptor.m_PadList[batchIndex] != noPad) || (padDescriptor.m_PadList[layout.GetChannelsIndex()] != noPad))
87  {
88  return false;
89  }
90 
91  const auto& padList = padDescriptor.m_PadList;
92 
93  // In Convolution2dDescriptor/Pooling2dDescriptor, padLeft and padRight are defined as paddings
94  // on width dimension whereas padTop and padBottom - paddings on height dimension, so updating
95  // these according to data layout
96  layerDescriptor.m_PadLeft += padList[layout.GetWidthIndex()].first;
97  layerDescriptor.m_PadRight += padList[layout.GetWidthIndex()].second;
98  layerDescriptor.m_PadTop += padList[layout.GetHeightIndex()].first;
99  layerDescriptor.m_PadBottom += padList[layout.GetHeightIndex()].second;
100 
101  return true;
102 }
unsigned int GetWidthIndex() const
unsigned int GetHeightIndex() const
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout...
bool IsNeutralElement(const Pooling2dDescriptor &descriptor, const TensorInfo &tensorInfo, const float tensorValue)
unsigned int GetChannelsIndex() const

◆ TryFoldPadIntoLayer2d() [2/2]

bool armnn::optimizations::pad_fold::TryFoldPadIntoLayer2d ( const PadDescriptor padDescriptor,
Pooling2dDescriptor poolDescriptor,
const TensorInfo tensorInfo 
)
inline

Definition at line 104 of file FoldPadIntoLayer2d.hpp.

References armnn::Exclude, armnn::IgnoreValue, Pooling2dDescriptor::m_PadBottom, Pooling2dDescriptor::m_PaddingMethod, Pooling2dDescriptor::m_PadLeft, Pooling2dDescriptor::m_PadRight, Pooling2dDescriptor::m_PadTop, Pooling2dDescriptor::m_PoolType, and armnn::Max.

106 {
107  const auto poolingPadValues = std::make_tuple(poolDescriptor.m_PadLeft, poolDescriptor.m_PadRight,
108  poolDescriptor.m_PadTop, poolDescriptor.m_PadBottom);
109  bool poolHasPadding = false;
110  if (poolingPadValues != std::make_tuple(0U, 0U, 0U, 0U))
111  {
112  poolHasPadding = true;
113  }
114 
115  // We cannot fold Average or L2 pooling if there's is already padding and that padding method is Exclude.
116  if (poolDescriptor.m_PoolType != PoolingAlgorithm::Max) // PoolingAlgorithm::Average or PoolingAlgorithm::L2
117  {
118  if ((poolHasPadding) && (poolDescriptor.m_PaddingMethod == PaddingMethod::Exclude))
119  {
120  return false;
121  }
122  }
123  poolDescriptor.m_PaddingMethod = PaddingMethod::IgnoreValue;
124 
125  return TryFoldPadIntoLayer2d<Pooling2dDescriptor>(padDescriptor, poolDescriptor, tensorInfo);
126 }