ArmNN
 22.08
EthosnRefConvolution2dWorkload.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 #include "EthosnRefConvImpl.hpp"
9 
10 using namespace armnn::ethosnref;
11 
12 namespace armnn
13 {
14 
15 static inline std::string Split(const std::string& s, const std::string& delim, std::size_t& pos)
16 {
17  if (pos >= s.length())
18  {
19  return "";
20  }
21 
22  std::size_t end = s.find(delim, pos);
23  if (end == std::string::npos)
24  {
25  end = s.length();
26  }
27 
28  std::string str = s.substr(pos, end - pos);
29  pos = end + 1;
30 
31  return str;
32 }
33 
35  const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info, bool winograd, std::string BlockConfigs)
36  : BaseWorkload<Convolution2dQueueDescriptor>(descriptor, info)
37 {
38  m_Weight = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Weight));
39 
40  if (descriptor.m_Parameters.m_BiasEnabled)
41  {
42  m_Bias = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Bias));
43  }
44 
45  m_Winograd = winograd;
46 
47  m_IsBlockConfigsWinograd2dCompatible = false;
48  std::string part;
49  std::size_t pos = 0;
50  while (!(part = Split(BlockConfigs, ",", pos)).empty())
51  {
52  if (part == "16x8")
53  {
54  m_IsBlockConfigsWinograd2dCompatible = true;
55  }
56  else if (part == "8x16")
57  {
58  m_IsBlockConfigsWinograd2dCompatible = true;
59  }
60  else if (part == "8x8")
61  {
62  m_IsBlockConfigsWinograd2dCompatible = true;
63  }
64  }
65  if (BlockConfigs == "")
66  {
67  m_IsBlockConfigsWinograd2dCompatible = true;
68  }
69 }
70 
71 
73 
74  ARMNN_SCOPED_PROFILING_EVENT_ETHOSN("EthosnRefConvolution2dWorkload_Execute");
75 
76  const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
77  const TensorInfo& weightsInfo = m_Weight->GetTensorInfo();
78 
79  bool useWinograd = false;
80 
81  if (m_Winograd == true) {
83  unsigned int weightsHeight = weightsInfo.GetShape()[dataLayoutIndexed.GetHeightIndex()];
84  unsigned int weightsWidth = weightsInfo.GetShape()[dataLayoutIndexed.GetWidthIndex()];
85  unsigned int xStride = m_Data.m_Parameters.m_StrideX;
86  unsigned int yStride = m_Data.m_Parameters.m_StrideY;
87 
88  bool isWinograd1D = weightsWidth == 1 || weightsHeight == 1;
89  bool isBlockSizeOk = isWinograd1D? true : m_IsBlockConfigsWinograd2dCompatible;
90 
91  uint32_t numMultsDirect, numMultsWinograd;
92 
93  if ( weightsWidth == 1 || weightsHeight == 1)
94  {
95  // 1D convolution kernel dim w x 1 or 1 x h
96  // numOfMultiplications = 2 * w or 2 * h DIRECT
97  // = 4 * CEIL(W/3) or 4 * CEIL(H/3) WINOGRAD
98  numMultsDirect = weightsWidth * weightsHeight * 2;
99  numMultsWinograd = 4 * DivideRoundUp(weightsWidth * weightsHeight, 3);
100  }
101  else
102  {
103  // 2D convolution kernel dim w x h
104  // numOfMultiplications = 4 * w * h DIRECT
105  // = 16 * CEIL(W/3) * CEIL(H/3) WINOGRAD
106  numMultsDirect = weightsWidth * weightsHeight * 4;
107  numMultsWinograd = 16 * DivideRoundUp(weightsWidth, 3) * DivideRoundUp(weightsHeight, 3);
108  }
109  if (numMultsWinograd < numMultsDirect &&
110  isBlockSizeOk &&
111  //TODO: FENCHSW-922 Need to revisit then when
112  // SW add support for Winogard + Strided
113  xStride == 1 && yStride == 1)
114  useWinograd = true;
115  }
116 
117  if (useWinograd == true)
118  {
119  std::cout << "[EthosNRef] Runnning in Winograd Mode.\n";
120  }
121  else
122  {
123  std::cout << "[EthosNRef] Runnning in Direct Mode.\n";
124  }
125 
126  if (CheckDataType(DataType::QSymmS16, inputInfo.GetDataType(), weightsInfo.GetDataType())) {
127  const int16_t* inputData = GetInputTensorData<int16_t>(0, m_Data);
128  const int16_t* weightsData = m_Weight->template GetConstTensor<int16_t>();
129  const int32_t* biasData = m_Data.m_Parameters.m_BiasEnabled ? m_Bias->template GetConstTensor<int32_t>() : nullptr;
130  const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
131 
132  if(useWinograd == false)
133  {
134  EthosnRefConvImpl<armnn::Convolution2dQueueDescriptor, int16_t, int16_t, int32_t, int64_t>(
135  m_Data,
136  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
137  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
138  biasData,
139  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
140  }
141  else
142  {
143  EthosnRefWinogradConvImpl<armnn::Convolution2dQueueDescriptor, int16_t, int16_t, int32_t>(
144  m_Data,
145  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
146  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
147  biasData,
148  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
149  }
150  }
151  else if (CheckDataType(DataType::QSymmS8, inputInfo.GetDataType(), weightsInfo.GetDataType())) {
152  const int8_t* inputData = GetInputTensorData<int8_t>(0, m_Data);
153  const int8_t* weightsData = m_Weight->template GetConstTensor<int8_t>();
154  const int32_t* biasData = m_Data.m_Parameters.m_BiasEnabled ? m_Bias->template GetConstTensor<int32_t>() : nullptr;
155  const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
156 
157  if(useWinograd == false)
158  {
159  EthosnRefConvImpl<armnn::Convolution2dQueueDescriptor, int8_t, int8_t, int32_t, int32_t>(
160  m_Data,
161  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
162  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
163  biasData,
164  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
165  }
166  else
167  {
168  EthosnRefWinogradConvImpl<armnn::Convolution2dQueueDescriptor, int8_t, int8_t, int32_t>(
169  m_Data,
170  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
171  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
172  biasData,
173  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
174  }
175  }
176  else { // QAsymmU8
177  assert(CheckDataType(DataType::QAsymmU8, inputInfo.GetDataType(), weightsInfo.GetDataType()));
178 
179  const uint8_t* inputData = GetInputTensorData<uint8_t>(0, m_Data);
180  const uint8_t* weightsData = m_Weight->template GetConstTensor<uint8_t>();
181  const int32_t* biasData = m_Data.m_Parameters.m_BiasEnabled ? m_Bias->template GetConstTensor<int32_t>() : nullptr;
182  const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
183 
184  if(useWinograd == false)
185  {
186  EthosnRefConvImpl<armnn::Convolution2dQueueDescriptor, uint8_t, uint8_t, int32_t, int32_t>(
187  m_Data,
188  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
189  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
190  biasData,
191  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
192  }
193  else
194  {
195  EthosnRefWinogradConvImpl<armnn::Convolution2dQueueDescriptor, uint8_t, uint8_t, int32_t>(
196  m_Data,
197  inputData, inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(),
198  weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
199  biasData,
200  outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), weightsInfo);
201  }
202  }
203 }
204 
205 } //namespace armnn
bool m_BiasEnabled
Enable/disable bias.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
unsigned int GetWidthIndex() const
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
EthosnRefConvolution2dWorkload(const Convolution2dQueueDescriptor &descriptor, const WorkloadInfo &info, bool winograd=false, std::string BlockConfigs="")
const ConstTensorHandle * m_Weight
const ConstTensorHandle * m_Bias
Copyright (c) 2021 ARM Limited and Contributors.
unsigned int GetHeightIndex() const
uint32_t DivideRoundUp(uint32_t numerator, uint32_t denominator)
bool CheckDataType(DataType type, DataType inputType, DataType weightsType)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:478
float GetQuantizationScale() const
Definition: Tensor.cpp:461
DataType GetDataType() const
Definition: Tensor.hpp:198
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout...
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
#define ARMNN_SCOPED_PROFILING_EVENT_ETHOSN(name)
std::vector< ITensorHandle * > m_Outputs
Contains information about TensorInfos of a layer.
std::vector< ITensorHandle * > m_Inputs
const TensorInfo & GetTensorInfo(const ITensorHandle *tensorHandle)
float32 helpers