ArmNN
 23.08
SpaceToBatchNd.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017-2019,2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "SpaceToBatchNd.hpp"
7 
9 
10 using namespace armnnUtils;
11 
12 namespace armnn
13 {
14 
15 unsigned int GetOffset(const TensorShape& shape,
16  unsigned int b,
17  unsigned int h,
18  unsigned int w,
19  unsigned int c,
20  const DataLayoutIndexed& dataLayout)
21 {
22  // 3D Tensors
23  unsigned int channelDimension3D = dataLayout.GetDataLayout() == DataLayout::NCHW ? 1 : 2;
24  if (shape.GetNumDimensions() == 3)
25  {
26  return (b * shape[dataLayout.GetHeightIndex()] + h) * shape[channelDimension3D] + c;
27  }
28  // 4D Tensors
29  else if (shape.GetNumDimensions() == 4)
30  {
31  if (dataLayout.GetDataLayout() == DataLayout::NHWC)
32  {
33  return ((b * shape[dataLayout.GetHeightIndex()] + h) * shape[dataLayout.GetWidthIndex()] + w) *
34  shape[dataLayout.GetChannelsIndex()] + c;
35  }
36  else
37  {
38  return ((b * shape[dataLayout.GetChannelsIndex()] + c) * shape[dataLayout.GetHeightIndex()] + h) *
39  shape[dataLayout.GetWidthIndex()] + w;
40  }
41  }
42  else
43  {
44  throw InvalidArgumentException("Tensor rank must be either 3 or 4", CHECK_LOCATION());
45  }
46 }
47 
48 void SpaceToBatchNd(const TensorInfo& inputInfo,
49  const TensorInfo& outputInfo,
50  const SpaceToBatchNdDescriptor& params,
51  Decoder<float>& inputData,
52  Encoder<float>& outputData)
53 {
54  unsigned int rank = inputInfo.GetNumDimensions();
55  if (rank != 3 && rank != 4 )
56  {
57  throw InvalidArgumentException("Tensor rank must be either 3 or 4, but it is " + std::to_string(rank),
58  CHECK_LOCATION());
59  }
60 
61  DataLayoutIndexed dataLayout = params.m_DataLayout;
62  unsigned int channelDimension3D = params.m_DataLayout == DataLayout::NCHW ? 1 : 2;
63 
64  const TensorShape& inputShape = inputInfo.GetShape();
65  const TensorShape& outputShape = outputInfo.GetShape();
66 
67  const unsigned int inputBatchSize = inputShape[0];
68  const unsigned int outputBatchSize = outputShape[0];
69 
70  const unsigned int channels = (rank == 3) ? inputShape[channelDimension3D]
71  : inputShape[dataLayout.GetChannelsIndex()];
72 
73  const unsigned int inputHeight = inputShape[dataLayout.GetHeightIndex()];
74  const unsigned int inputWidth = (rank == 3) ? 1 : inputShape[dataLayout.GetWidthIndex()];
75  const unsigned int outputHeight = outputShape[dataLayout.GetHeightIndex()];
76  const unsigned int outputWidth = (rank == 3) ? 1 : outputShape[dataLayout.GetWidthIndex()];
77 
78  const unsigned int blockHeight = params.m_BlockShape[0];
79  const unsigned int blockWidth = (rank == 3) ? 1 : params.m_BlockShape[1];
80 
81  const unsigned int paddingTop = params.m_PadList[0].first;
82  const unsigned int paddingLeft = (rank == 3) ? 0 : params.m_PadList[1].first;
83 
84  for (unsigned int outB = 0; outB < outputBatchSize; ++outB)
85  {
86  unsigned int inB = outB % inputBatchSize;
87 
88  unsigned int shiftW = (outB / inputBatchSize) % blockWidth;
89  unsigned int shiftH = (outB / inputBatchSize) / blockWidth;
90 
91  for (unsigned int outH = 0; outH < outputHeight; ++outH)
92  {
93  for (unsigned int outW = 0; outW < outputWidth; ++outW)
94  {
95  if (outH * blockHeight + shiftH < paddingTop ||
96  outH * blockHeight + shiftH >= paddingTop + inputHeight ||
97  outW * blockWidth + shiftW < paddingLeft ||
98  outW * blockWidth + shiftW >= paddingLeft + inputWidth)
99  {
100  for (unsigned int c = 0; c < channels; c++)
101  {
102  unsigned int outOffset = GetOffset(outputShape,
103  outB,
104  outH,
105  outW,
106  c,
107  dataLayout);
108  outputData += outOffset;
109  outputData.Set(0);
110  outputData -= outOffset;
111  }
112  }
113  else
114  {
115  for (unsigned int c = 0; c < channels; c++)
116  {
117  unsigned int inOffset = GetOffset(inputShape,
118  inB,
119  (outH * blockHeight + shiftH) - paddingTop,
120  (outW * blockWidth + shiftW) - paddingLeft,
121  c,
122  dataLayout);
123 
124  unsigned int outOffset = GetOffset(outputShape,
125  outB,
126  outH,
127  outW,
128  c,
129  dataLayout);
130 
131  outputData += outOffset;
132  inputData += inOffset;
133  outputData.Set(inputData.Get());
134  inputData -= inOffset;
135  outputData -= outOffset;
136  }
137  }
138  }
139  }
140  }
141 }
142 
143 } //namespace armnn
armnn::Decoder< float >
armnn::Encoder::Set
virtual void Set(IType right)=0
armnn::SpaceToBatchNdDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1050
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
CHECK_LOCATION
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
armnnUtils::DataLayoutIndexed
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
Definition: DataLayoutIndexed.hpp:17
armnnUtils::DataLayoutIndexed::GetDataLayout
armnn::DataLayout GetDataLayout() const
Definition: DataLayoutIndexed.hpp:22
armnn::SpaceToBatchNdDescriptor::m_BlockShape
std::vector< unsigned int > m_BlockShape
Block shape value.
Definition: Descriptors.hpp:1045
armnn::GetOffset
unsigned int GetOffset(const TensorShape &shape, unsigned int b, unsigned int h, unsigned int w, unsigned int c, const DataLayoutIndexed &dataLayout)
Definition: SpaceToBatchNd.cpp:15
armnnUtils::DataLayoutIndexed::GetHeightIndex
unsigned int GetHeightIndex() const
Definition: DataLayoutIndexed.hpp:24
armnn::SpaceToBatchNdDescriptor::m_PadList
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding values for the input dimension: heightPad{top, bottom} widthPad{left,...
Definition: Descriptors.hpp:1048
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::Encoder< float >
armnn::TensorShape::GetNumDimensions
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
armnnUtils
Definition: CompatibleTypes.hpp:10
armnn::InvalidArgumentException
Definition: Exceptions.hpp:80
armnn::SpaceToBatchNdDescriptor
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
Definition: Descriptors.hpp:1022
armnnUtils::DataLayoutIndexed::GetWidthIndex
unsigned int GetWidthIndex() const
Definition: DataLayoutIndexed.hpp:25
armnn::SpaceToBatchNd
void SpaceToBatchNd(const TensorInfo &inputInfo, const TensorInfo &outputInfo, const SpaceToBatchNdDescriptor &params, Decoder< float > &inputData, Encoder< float > &outputData)
Definition: SpaceToBatchNd.cpp:48
armnn::Decoder::Get
virtual IType Get() const =0
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
SpaceToBatchNd.hpp
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnnUtils::DataLayoutIndexed::GetChannelsIndex
unsigned int GetChannelsIndex() const
Definition: DataLayoutIndexed.hpp:23
DataLayoutIndexed.hpp