ArmNN
 21.02
QuantizerStrategy.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "QuantizerStrategy.hpp"
8 
9 namespace armnn
10 {
11 
13  const IQuantizationScheme* quantizationScheme,
14  bool preserveType)
15  : m_Ranges(rangeTracker)
16  , m_QuantizedNetwork(INetwork::Create())
17  , m_QuantizationScheme(quantizationScheme)
18  , m_PreserveType(preserveType)
19 {
20 }
21 
22 void QuantizerStrategy::SetQuantizedInputConnections(const IConnectableLayer* srcLayer,
23  IConnectableLayer* quantizedLayer)
24 {
25  ARMNN_ASSERT(srcLayer);
26  for (unsigned int i = 0; i < srcLayer->GetNumInputSlots(); i++)
27  {
28  const IInputSlot& srcInputSlot = srcLayer->GetInputSlot(i);
29  const InputSlot* inputSlot = static_cast<const InputSlot*>(&srcInputSlot);
30  ARMNN_ASSERT(inputSlot);
31  const OutputSlot* outputSlot = inputSlot->GetConnectedOutputSlot();
32 
33  ARMNN_ASSERT(outputSlot);
34  unsigned int slotIdx = outputSlot->CalculateIndexOnOwner();
35  Layer& layerToFind = outputSlot->GetOwningLayer();
36 
37  auto found = m_OriginalToQuantizedGuidMap.find(layerToFind.GetGuid());
38  if (found == m_OriginalToQuantizedGuidMap.end())
39  {
40  // Error in graph traversal order
41  ARMNN_ASSERT_MSG(false, "Error in graph traversal");
42  return;
43  }
44 
45  // Connect the slots in the quantized model
46  IConnectableLayer* prevQuantizedLayer = m_QuantizedGuidToLayerMap[found->second];
47  IInputSlot& newInputSlot = quantizedLayer->GetInputSlot(i);
48  IOutputSlot& newOutputSlot = prevQuantizedLayer->GetOutputSlot(slotIdx);
49  newOutputSlot.Connect(newInputSlot);
50  TensorInfo info(outputSlot->GetTensorInfo());
51 
52  // Only try to set quantization params on tensors that can be quantized
56  {
57  // Fetch the min/max ranges that were computed earlier
58  auto range = m_Ranges.GetRange(layerToFind.GetGuid(), slotIdx);
59  OffsetScalePair qParams = m_QuantizationScheme->ComputeScheme(range.first, range.second);
60  info.SetDataType(m_QuantizationScheme->GetDataType());
61  info.SetQuantizationOffset(qParams.second);
62  info.SetQuantizationScale(qParams.first);
63  }
64  newOutputSlot.SetTensorInfo(info);
65  }
66 }
67 
68 ConstTensor QuantizerStrategy::CreateQuantizedBias(const IConnectableLayer* srcLayer,
69  const ConstTensor& weights,
70  const Optional<ConstTensor>& biases,
71  std::vector<int32_t>& backing)
72 {
73  ARMNN_ASSERT(srcLayer);
74  const IInputSlot& srcInputSlot = srcLayer->GetInputSlot(0);
75  auto inputSlot = static_cast<const InputSlot*>(&srcInputSlot);
76  ARMNN_ASSERT(inputSlot);
77  const OutputSlot* outputSlot = inputSlot->GetConnectedOutputSlot();
78 
79  ARMNN_ASSERT(outputSlot);
80  unsigned int slotIdx = outputSlot->CalculateIndexOnOwner();
81  Layer& layerToFind = outputSlot->GetOwningLayer();
82 
83  auto found = m_OriginalToQuantizedGuidMap.find(layerToFind.GetGuid());
84  if (found == m_OriginalToQuantizedGuidMap.end())
85  {
86  // Error in graph traversal order
87  ARMNN_ASSERT_MSG(false, "Error in graph traversal");
88  return biases.value();
89  }
90 
91  // Fetch the min/max ranges that were computed earlier
92  auto range = m_Ranges.GetRange(layerToFind.GetGuid(), slotIdx);
93  OffsetScalePair qParams = m_QuantizationScheme->ComputeScheme(range.first, range.second);
94 
95  // Get the quantization scale based on input and weight scale
96  float scale = qParams.first * weights.GetInfo().GetQuantizationScale();
97 
98  // Set up quantized bias tensor info and allocate space
99  TensorInfo qInfo(biases.value().GetInfo().GetShape(), DataType::Signed32, scale, 0);
100  backing.resize(biases.value().GetInfo().GetNumElements());
101 
102  // Convert values to int32
103  for (size_t i = 0; i < backing.size(); ++i)
104  {
105  float fp32Value = static_cast<const float*>(biases.value().GetMemoryArea())[i];
106  backing[i] = armnn::numeric_cast<int32_t>(fp32Value * ( 1 / scale ));
107  }
108 
109  return ConstTensor(qInfo, backing);
110 }
111 
112 void QuantizerStrategy::RecordLayer(const IConnectableLayer* srcLayer, IConnectableLayer* quantizedLayer)
113 {
114  m_OriginalToQuantizedGuidMap.insert(std::make_pair(srcLayer->GetGuid(), quantizedLayer->GetGuid()));
115  m_QuantizedGuidToLayerMap.insert(std::make_pair(quantizedLayer->GetGuid(), quantizedLayer));
116 }
117 
119  const BaseDescriptor& descriptor,
120  const std::vector<armnn::ConstTensor> &constants,
121  const char *name,
122  const armnn::LayerBindingId id)
123 {
124  IgnoreUnused(id);
125 
126  IConnectableLayer* newLayer;
127 
128  switch (layer->GetType())
129  {
131  {
132  newLayer = m_QuantizedNetwork->AddAdditionLayer(name);
133  break;
134  }
136  {
137  const ActivationDescriptor& activationDescriptor = static_cast<const ActivationDescriptor&>(descriptor);
138  newLayer = m_QuantizedNetwork->AddActivationLayer(activationDescriptor, name);
139  break;
140  }
142  {
143  ArgMinMaxDescriptor argMinMaxDescriptor = static_cast<const ArgMinMaxDescriptor&>(descriptor);
144  newLayer = m_QuantizedNetwork->AddArgMinMaxLayer(argMinMaxDescriptor, name);
145  break;
146  }
148  {
149 
150  BatchNormalizationDescriptor batchNormalizationDescriptor =
151  static_cast<const BatchNormalizationDescriptor&>(descriptor);
152  std::vector<uint8_t> meanBacking;
153  ConstTensor qMean = CreateQuantizedConst(constants[0], meanBacking);
154 
155  std::vector<uint8_t> varianceBacking;
156  ConstTensor qVariance = CreateQuantizedConst(constants[1], varianceBacking);
157 
158  std::vector<uint8_t> betaBacking;
159  ConstTensor qBeta = CreateQuantizedConst(constants[2], betaBacking);
160 
161  std::vector<uint8_t> gammaBacking;
162  ConstTensor qGamma = CreateQuantizedConst(constants[3], gammaBacking);
163 
164  newLayer = m_QuantizedNetwork->AddBatchNormalizationLayer(batchNormalizationDescriptor,
165  qMean,
166  qVariance,
167  qBeta,
168  qGamma,
169  name);
170  break;
171  }
173  {
174  BatchToSpaceNdDescriptor batchToSpaceNdDescriptor =
175  static_cast<const BatchToSpaceNdDescriptor&>(descriptor);
176 
177  newLayer = m_QuantizedNetwork->AddBatchToSpaceNdLayer(batchToSpaceNdDescriptor, name);
178  break;
179  }
181  {
182  ComparisonDescriptor comparisonDescriptor =static_cast<const ComparisonDescriptor&>(descriptor);
183  newLayer = m_QuantizedNetwork->AddComparisonLayer(comparisonDescriptor, name);
184  break;
185  }
187  {
188  OriginsDescriptor originsDescriptor = static_cast<const OriginsDescriptor&>(descriptor);
189  newLayer = m_QuantizedNetwork->AddConcatLayer(originsDescriptor, name);
190  break;
191  }
193  {
194  std::vector<uint8_t> inputBacking;
195  ConstTensor qInput = CreateQuantizedConst(constants[0], inputBacking);
196 
197  newLayer = m_QuantizedNetwork->AddConstantLayer(qInput, name);
198  break;
199  }
201  {
202  const armnn::Optional<ConstTensor> biases = constants.size() == 1 ?
204  armnn::Optional<ConstTensor>(constants[1]);
205 
206  std::vector<uint8_t> weightsBacking;
207  ConstTensor qWeights = CreateQuantizedConst(constants[0], weightsBacking);
208  Optional<ConstTensor> optionalQBiases;
209  std::vector<int32_t> biasesBacking;
210 
211  if (biases.has_value())
212  {
213  ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
214  optionalQBiases = Optional<ConstTensor>(qBiases);
215  }
216  Convolution2dDescriptor convolution2dDescriptor = static_cast<const Convolution2dDescriptor&>(descriptor);
217 
218  newLayer = m_QuantizedNetwork->AddConvolution2dLayer(convolution2dDescriptor,
219  qWeights,
220  optionalQBiases,
221  name);
222  break;
223  }
225  {
226  DepthToSpaceDescriptor depthToSpaceDescriptor = static_cast<const DepthToSpaceDescriptor&>(descriptor);
227 
228  newLayer = m_QuantizedNetwork->AddDepthToSpaceLayer(depthToSpaceDescriptor, name);
229  break;
230  }
232  {
233  DepthwiseConvolution2dDescriptor depthwiseConvolution2dDescriptor =
234  static_cast<const DepthwiseConvolution2dDescriptor&>(descriptor);
235 
236  const armnn::Optional<ConstTensor> biases = constants.size() == 1 ?
238  armnn::Optional<ConstTensor>(constants[1]);
239 
240  std::vector<uint8_t> weightsBacking;
241  ConstTensor qWeights = CreateQuantizedConst(constants[0], weightsBacking);
242  Optional<ConstTensor> optionalQBiases;
243  std::vector<int32_t> biasesBacking;
244 
245  if (biases.has_value())
246  {
247  ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
248  optionalQBiases = Optional<ConstTensor>(qBiases);
249  }
250 
251  newLayer = m_QuantizedNetwork->AddDepthwiseConvolution2dLayer(
252  depthwiseConvolution2dDescriptor,
253  qWeights,
254  optionalQBiases,
255  name);
256  break;
257  }
259  {
260  ElementwiseUnaryDescriptor elementwiseUnaryDescriptor =
261  static_cast<const ElementwiseUnaryDescriptor&>(descriptor);
262 
263  newLayer = m_QuantizedNetwork->AddElementwiseUnaryLayer(elementwiseUnaryDescriptor, name);
264  break;
265  }
267  {
268  FillDescriptor fillDescriptor = static_cast<const FillDescriptor&>(descriptor);
269 
270  newLayer = m_QuantizedNetwork->AddFillLayer(fillDescriptor, name);
271  break;
272  }
274  {
275  FullyConnectedDescriptor fullyConnectedDescriptor =
276  static_cast<const FullyConnectedDescriptor&>(descriptor);
277 
278  const armnn::Optional<ConstTensor> biases = constants.size() == 1 ?
280  armnn::Optional<ConstTensor>(constants[1]);
281 
282  std::vector<uint8_t> weightsBacking;
283  ConstTensor qWeights = CreateQuantizedConst(constants[0], weightsBacking);
284  Optional<ConstTensor> optionalQBiases;
285  std::vector<int32_t> biasesBacking;
286 
287  if (biases.has_value())
288  {
289  ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
290  optionalQBiases = Optional<ConstTensor>(qBiases);
291  }
292 
293  newLayer = m_QuantizedNetwork->AddFullyConnectedLayer(fullyConnectedDescriptor,
294  qWeights,
295  optionalQBiases,
296  name);
297  break;
298  }
300  {
301  const DataType dataType = layer->GetOutputSlot(0).GetTensorInfo().GetDataType();
302  IConnectableLayer* inputLayer = m_QuantizedNetwork->AddInputLayer(id, name);
303 
304  if (m_PreserveType && (dataType == DataType::Float32 || dataType == DataType::Float16))
305  {
306  IConnectableLayer* quantizeLayer = m_QuantizedNetwork->AddQuantizeLayer();
307  inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
308  inputLayer->GetOutputSlot(0).SetTensorInfo(layer->GetOutputSlot(0).GetTensorInfo());
309  RecordLayer(layer, quantizeLayer);
310  return;
311  }
312  else
313  {
314  RecordLayer(layer, inputLayer);
315  return;
316  }
317  }
319  {
320  InstanceNormalizationDescriptor instanceNormalizationDescriptor =
321  static_cast<const InstanceNormalizationDescriptor&>(descriptor);
322 
323  newLayer =
324  m_QuantizedNetwork->AddInstanceNormalizationLayer(instanceNormalizationDescriptor, name);
325  break;
326  }
328  {
329  LogSoftmaxDescriptor logSoftmaxDescriptor = static_cast<const LogSoftmaxDescriptor&>(descriptor);
330 
331  newLayer = m_QuantizedNetwork->AddLogSoftmaxLayer(logSoftmaxDescriptor, name);
332  break;
333  }
335  {
336  MeanDescriptor meanDescriptor = static_cast<const MeanDescriptor&>(descriptor);
337 
338  newLayer = m_QuantizedNetwork->AddMeanLayer(meanDescriptor, name);
339  break;
340  }
342  {
343  newLayer = m_QuantizedNetwork->AddMultiplicationLayer(name);
344  break;
345  }
347  {
348  NormalizationDescriptor normalizationDescriptor = static_cast<const NormalizationDescriptor&>(descriptor);
349 
350  newLayer = m_QuantizedNetwork->AddNormalizationLayer(normalizationDescriptor, name);
351  break;
352  }
354  {
355  const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
356  const DataType& dataType = info.GetDataType();
357  newLayer = m_QuantizedNetwork->AddOutputLayer(id, name);
358 
359  if (m_PreserveType && (dataType == DataType::Float32 || dataType == DataType::Float16))
360  {
361  IConnectableLayer* dequantizeLayer = m_QuantizedNetwork->AddDequantizeLayer();
362  RecordLayer(layer, dequantizeLayer);
363  SetQuantizedInputConnections(layer, dequantizeLayer);
364  dequantizeLayer->GetOutputSlot(0).Connect(newLayer->GetInputSlot(0));
365  dequantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
366  return;
367  }
368  else
369  {
370  break;
371  }
372  }
373  case armnn::LayerType::Pad :
374  {
375  PadDescriptor padDescriptor = static_cast<const PadDescriptor&>(descriptor);
376 
377  newLayer = m_QuantizedNetwork->AddPadLayer(padDescriptor, name);
378  break;
379  }
381  {
382  PermuteDescriptor permuteDescriptor = static_cast<const PermuteDescriptor&>(descriptor);
383 
384  newLayer = m_QuantizedNetwork->AddPermuteLayer(permuteDescriptor, name);
385  break;
386  }
388  {
389  Pooling2dDescriptor pooling2dDescriptor = static_cast<const Pooling2dDescriptor&>(descriptor);
390 
391  newLayer = m_QuantizedNetwork->AddPooling2dLayer(pooling2dDescriptor, name);
392  break;
393  }
395  {
396  newLayer = m_QuantizedNetwork->AddPreluLayer(name);
397  break;
398  }
400  {
401  ReshapeDescriptor reshapeDescriptor = static_cast<const ReshapeDescriptor&>(descriptor);
402 
403  newLayer = m_QuantizedNetwork->AddReshapeLayer(reshapeDescriptor, name);
404  break;
405  }
407  {
408 
409  ResizeBilinearDescriptor resizeBilinearDescriptor =
410  static_cast<const ResizeBilinearDescriptor&>(descriptor);
411 
412  ResizeDescriptor resizeDescriptor;
413  resizeDescriptor.m_Method = ResizeMethod::Bilinear;
414  resizeDescriptor.m_TargetWidth = resizeBilinearDescriptor.m_TargetWidth;
415  resizeDescriptor.m_TargetHeight = resizeBilinearDescriptor.m_TargetHeight;
416  resizeDescriptor.m_DataLayout = resizeBilinearDescriptor.m_DataLayout;
417 
418  newLayer = m_QuantizedNetwork->AddResizeLayer(resizeDescriptor, name);
419  break;
420  }
422  {
423  SliceDescriptor sliceDescriptor = static_cast<const SliceDescriptor&>(descriptor);
424 
425  newLayer = m_QuantizedNetwork->AddSliceLayer(sliceDescriptor, name);
426  break;
427  }
429  {
430  SoftmaxDescriptor softmaxDescriptor = static_cast<const SoftmaxDescriptor&>(descriptor);
431 
432  newLayer = m_QuantizedNetwork->AddSoftmaxLayer(softmaxDescriptor, name);
433  break;
434  }
436  {
437  SpaceToBatchNdDescriptor spaceToBatchNdDescriptor =
438  static_cast<const SpaceToBatchNdDescriptor&>(descriptor);
439 
440  newLayer = m_QuantizedNetwork->AddSpaceToBatchNdLayer(spaceToBatchNdDescriptor, name);
441  break;
442  }
444  {
445  SpaceToDepthDescriptor spaceToDepthDescriptor = static_cast<const SpaceToDepthDescriptor&>(descriptor);
446  newLayer = m_QuantizedNetwork->AddSpaceToDepthLayer(spaceToDepthDescriptor, name);
447  break;
448  }
450  {
451  SplitterDescriptor splitterDescriptor = static_cast<const SplitterDescriptor&>(descriptor);
452  newLayer = m_QuantizedNetwork->AddSplitterLayer(splitterDescriptor, name);
453  break;
454  }
456  {
457  StackDescriptor stackDescriptor = static_cast<const StackDescriptor&>(descriptor);
458 
459  newLayer = m_QuantizedNetwork->AddStackLayer(stackDescriptor, name);
460  break;
461  }
463  {
464  StridedSliceDescriptor stridedSliceDescriptor = static_cast<const StridedSliceDescriptor&>(descriptor);
465 
466  newLayer = m_QuantizedNetwork->AddStridedSliceLayer(stridedSliceDescriptor, name);
467  break;
468  }
470  {
471  newLayer = m_QuantizedNetwork->AddSubtractionLayer( name);
472  break;
473  }
475  {
476 
477  const armnn::Optional<ConstTensor> biases = constants.size() == 1 ?
479  armnn::Optional<ConstTensor>(constants[1]);
480  // quantize weights
481  std::vector<uint8_t> weightsBacking;
482  ConstTensor qWeights = CreateQuantizedConst(constants[0], weightsBacking);
483 
484  // quantize biases
485  std::vector<int32_t> biasesBacking;
486  Optional<ConstTensor> optionalQBiases;
487  if (biases.has_value())
488  {
489  ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
490  optionalQBiases = Optional<ConstTensor>(qBiases);
491  }
492 
493  TransposeConvolution2dDescriptor transposeConvolution2dDescriptor =
494  static_cast<const TransposeConvolution2dDescriptor&>(descriptor);
495 
496  newLayer = m_QuantizedNetwork->AddTransposeConvolution2dLayer(transposeConvolution2dDescriptor,
497  qWeights,
498  optionalQBiases,
499  name);
500  break;
501  }
503  {
504  TransposeDescriptor transposeDescriptor = static_cast<const TransposeDescriptor&>(descriptor);
505 
506  newLayer = m_QuantizedNetwork->AddTransposeLayer(transposeDescriptor, name);
507  break;
508  }
509  default:
510  {
511  throw UnimplementedException("Unimplemented layer encountered");
512  }
513  }
514  RecordLayer(layer, newLayer);
515  SetQuantizedInputConnections(layer, newLayer);
516 }
517 
518 }
519 
std::pair< float, int > OffsetScalePair
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:62
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
A ReshapeDescriptor for the ReshapeLayer.
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:78
uint32_t m_TargetWidth
Target width value.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
A Convolution2dDescriptor for the Convolution2dLayer.
Layer & GetOwningLayer() const
Definition: Layer.hpp:115
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
void ExecuteStrategy(const armnn::IConnectableLayer *layer, const BaseDescriptor &descriptor, const std::vector< armnn::ConstTensor > &constants, const char *name, const armnn::LayerBindingId id) override
Main network class which provides the interface for building up a neural network. ...
Definition: INetwork.hpp:178
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
virtual OffsetScalePair ComputeScheme(double min, double max) const =0
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:210
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
A ResizeDescriptor for the ResizeLayer.
MinMaxRange GetRange(LayerGuid guid, unsigned int idx) const
Retrieve the Range for a particular output slot on a particular layer.
Base class for all descriptors.
Definition: Descriptors.hpp:22
A StackDescriptor for the StackLayer.
A PadDescriptor for the PadLayer.
DataType
Definition: Types.hpp:32
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
An output connection slot for a layer.
Definition: INetwork.hpp:38
QuantizerStrategy(const RangeTracker &rangeTracker, const IQuantizationScheme *quantizationScheme, bool preserveType)
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:56
float GetQuantizationScale() const
Definition: Tensor.cpp:452
DataType GetDataType() const
Definition: Tensor.hpp:194
An OriginsDescriptor for the ConcatLayer.
bool has_value() const noexcept
Definition: Optional.hpp:53
A FullyConnectedDescriptor for the FullyConnectedLayer.
virtual LayerGuid GetGuid() const =0
Returns the unique id of the layer.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:314
uint32_t m_TargetWidth
Target width value.
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:55
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:25
const TensorInfo & GetInfo() const
Definition: Tensor.hpp:282
uint32_t m_TargetHeight
Target height value.
uint32_t m_TargetHeight
Target height value.
A SliceDescriptor for the SliceLayer.
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
virtual DataType GetDataType() const =0
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:98
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
A MeanDescriptor for the MeanLayer.
virtual const IOutputSlot * GetConnection() const =0
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
virtual int Connect(IInputSlot &destination)=0
A Pooling2dDescriptor for the Pooling2dLayer.
ConstTensor CreateQuantizedConst(const ConstTensor &tensor, std::vector< uint8_t > &backing)
A NormalizationDescriptor for the NormalizationLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
A ResizeBilinearDescriptor for the ResizeBilinearLayer.
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63
A SoftmaxDescriptor for the SoftmaxLayer.
An input connection slot for a layer.
Definition: INetwork.hpp:25
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A FillDescriptor for the FillLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
A PermuteDescriptor for the PermuteLayer.
LayerGuid GetGuid() const final
Returns the unique id of the layer.
Definition: Layer.hpp:322
unsigned int CalculateIndexOnOwner() const override
Definition: Layer.cpp:130