ArmNN
 22.11
TensorUtils.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
11 
12 #include <fmt/format.h>
13 
14 using namespace armnn;
15 
16 namespace armnnUtils
17 {
18 
19 TensorShape GetTensorShape(unsigned int numberOfBatches,
20  unsigned int numberOfChannels,
21  unsigned int height,
22  unsigned int width,
23  const DataLayout dataLayout)
24 {
25  switch (dataLayout)
26  {
27  case DataLayout::NCHW:
28  return TensorShape({numberOfBatches, numberOfChannels, height, width});
29  case DataLayout::NHWC:
30  return TensorShape({numberOfBatches, height, width, numberOfChannels});
31  default:
32  throw InvalidArgumentException("Unknown data layout ["
33  + std::to_string(static_cast<int>(dataLayout)) +
34  "]", CHECK_LOCATION());
35  }
36 }
37 
38 TensorInfo GetTensorInfo(unsigned int numberOfBatches,
39  unsigned int numberOfChannels,
40  unsigned int height,
41  unsigned int width,
42  const DataLayout dataLayout,
43  const DataType dataType)
44 {
45  switch (dataLayout)
46  {
47  case DataLayout::NCHW:
48  return TensorInfo({numberOfBatches, numberOfChannels, height, width}, dataType);
49  case DataLayout::NHWC:
50  return TensorInfo({numberOfBatches, height, width, numberOfChannels}, dataType);
51  default:
52  throw InvalidArgumentException("Unknown data layout ["
53  + std::to_string(static_cast<int>(dataLayout)) +
54  "]", CHECK_LOCATION());
55  }
56 }
57 
58 TensorInfo GetTensorInfo(unsigned int numberOfBatches,
59  unsigned int numberOfChannels,
60  unsigned int depth,
61  unsigned int height,
62  unsigned int width,
63  const DataLayout dataLayout,
64  const DataType dataType)
65 {
66  switch (dataLayout)
67  {
68  case DataLayout::NDHWC:
69  return TensorInfo({numberOfBatches, depth, height, width, numberOfChannels}, dataType);
70  case DataLayout::NCDHW:
71  return TensorInfo({numberOfBatches, numberOfChannels, depth, height, width}, dataType);
72  default:
73  throw InvalidArgumentException("Unknown data layout ["
74  + std::to_string(static_cast<int>(dataLayout)) +
75  "]", CHECK_LOCATION());
76  }
77 }
78 
79 std::pair<float, float> FindMinMax(ITensorHandle* tensorHandle)
80 {
81  auto tensor_data = static_cast<const float *>(tensorHandle->Map(true));
82  auto tensor_size = tensorHandle->GetShape().GetNumElements();
83 
84  // Set min/max initially to first value in tensor
85  float min = tensor_data[0];
86  float max = tensor_data[0];
87 
88  // Loop over rest of tensor and update min/max if necessary
89  for (unsigned int val = 1; val < tensor_size; val++)
90  {
91  if (tensor_data[val] < min)
92  {
93  min = tensor_data[val];
94  }
95  else if (tensor_data[val] > max)
96  {
97  max = tensor_data[val];
98  }
99  }
100 
101  tensorHandle->Unmap();
102 
103  return std::make_pair(min, max);
104 }
105 
106 TensorShape ExpandDims(const TensorShape& tensorShape, int axis)
107 {
108  unsigned int outputDim = tensorShape.GetNumDimensions() + 1;
109 
110  if (axis < -armnn::numeric_cast<int>(outputDim) || axis > armnn::numeric_cast<int>(tensorShape.GetNumDimensions()))
111  {
112  throw InvalidArgumentException(fmt::format("Invalid expansion axis {} for {}D input tensor. {}",
113  axis,
114  tensorShape.GetNumDimensions(),
115  CHECK_LOCATION().AsString()));
116  }
117 
118  if (axis < 0)
119  {
120  axis = armnn::numeric_cast<int>(outputDim) + axis;
121  }
122 
123  std::vector<unsigned int> outputShape;
124  outputShape.reserve(tensorShape.GetNumDimensions());
125  for (unsigned int i = 0; i < tensorShape.GetNumDimensions(); ++i)
126  {
127  outputShape.push_back(tensorShape[i]);
128  }
129  outputShape.insert(outputShape.begin() + axis, 1);
130 
131  return TensorShape(outputDim, outputShape.data());
132 }
133 
134 std::vector<unsigned int> SqueezeDims(const TensorShape& tensorShape)
135 {
136  unsigned int outputDimSize = 0;
137  std::vector<unsigned int> squeezedDims;
138 
139  for (unsigned int i = 0; i < tensorShape.GetNumDimensions(); ++i)
140  {
141  if (tensorShape[i] != 1)
142  {
143  squeezedDims.push_back(tensorShape[i]);
144  ++outputDimSize;
145  }
146  }
147  return squeezedDims;
148 }
149 
150 unsigned int GetNumElementsBetween(const TensorShape& shape,
151  const unsigned int firstAxisInclusive,
152  const unsigned int lastAxisExclusive)
153 {
154  ARMNN_ASSERT(firstAxisInclusive <= lastAxisExclusive);
155  ARMNN_ASSERT(lastAxisExclusive <= shape.GetNumDimensions());
156  unsigned int count = 1;
157  for (unsigned int i = firstAxisInclusive; i < lastAxisExclusive; i++)
158  {
159  count *= shape[i];
160  }
161  return count;
162 }
163 
164 unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
165 {
166  ARMNN_ASSERT_MSG(axis < armnn::numeric_cast<int>(inputDimension),
167  "Required axis index greater than number of dimensions.");
168  ARMNN_ASSERT_MSG(axis >= -armnn::numeric_cast<int>(inputDimension),
169  "Required axis index lower than negative of the number of dimensions");
170 
171  unsigned int uAxis = axis < 0 ?
172  inputDimension - armnn::numeric_cast<unsigned int>(abs(axis))
173  : armnn::numeric_cast<unsigned int>(axis);
174  return uAxis;
175 }
176 
177 unsigned int GetNumElementsAfter(const armnn::TensorShape& shape, unsigned int axis)
178 {
179  unsigned int numDim = shape.GetNumDimensions();
180  ARMNN_ASSERT(axis <= numDim - 1);
181  unsigned int count = 1;
182  for (unsigned int i = axis+1; i < numDim; i++)
183  {
184  count *= shape[i];
185  }
186  return count;
187 }
188 
189 std::pair<unsigned int, std::vector<float>> GetPerAxisParams(const armnn::TensorInfo& info)
190 {
191  const std::vector<float>& scales = info.GetQuantizationScales();
192  armnn::Optional<unsigned int> quantizationDim = info.GetQuantizationDim();
193  if (!info.HasPerAxisQuantization())
194  {
196  std::string("Per-axis quantization params not set for tensor of type ") +
198  }
199  unsigned int axisFactor = GetNumElementsAfter(info.GetShape(), quantizationDim.value()) ;
200 
201  return { axisFactor, scales };
202 }
203 
204 } // namespace armnnUtils
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified...
Definition: Tensor.cpp:181
DataLayout
Definition: Types.hpp:62
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
std::vector< unsigned int > SqueezeDims(const armnn::TensorShape &tensorShape)
bool HasPerAxisQuantization() const
Definition: Tensor.cpp:446
unsigned int GetNumElementsBetween(const armnn::TensorShape &shape, unsigned int firstAxisInclusive, unsigned int lastAxisExclusive)
Optional< unsigned int > GetQuantizationDim() const
Definition: Tensor.cpp:494
std::pair< unsigned int, std::vector< float > > GetPerAxisParams(const armnn::TensorInfo &info)
Copyright (c) 2021 ARM Limited and Contributors.
std::vector< float > GetQuantizationScales() const
Definition: Tensor.cpp:451
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:202
DataType
Definition: Types.hpp:48
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
DataType GetDataType() const
Definition: Tensor.hpp:198
unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
std::pair< float, float > FindMinMax(armnn::ITensorHandle *tensorHandle)
Definition: TensorUtils.cpp:79
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::TensorShape GetTensorShape(unsigned int numberOfBatches, unsigned int numberOfChannels, unsigned int height, unsigned int width, const armnn::DataLayout dataLayout)
Definition: TensorUtils.cpp:19
armnn::TensorShape ExpandDims(const armnn::TensorShape &tensorShape, int axis)
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
virtual TensorShape GetShape() const =0
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
virtual const void * Map(bool blocking=true) const =0
Map the tensor data for access.
virtual void Unmap() const =0
Unmap the tensor data.
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
unsigned int GetNumElementsAfter(const armnn::TensorShape &shape, unsigned int axis)
const TensorInfo & GetTensorInfo(const ITensorHandle *tensorHandle)
float32 helpers