1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "Network.hpp"
7 #include "NetworkQuantizerUtils.hpp"
8 #include "QuantizerVisitor.hpp"
9 #include "StaticRangeVisitor.hpp"
10
11 #include <armnn/utility/NumericCast.hpp>
12 #include <armnn/utility/PolymorphicDowncast.hpp>
13
14 namespace armnn
15 {
16
QuantizerVisitor(const RangeTracker & rangeTracker,const IQuantizationScheme * quantizationScheme,bool preserveType)17 QuantizerVisitor::QuantizerVisitor(const RangeTracker& rangeTracker,
18 const IQuantizationScheme* quantizationScheme,
19 bool preserveType)
20 : m_Ranges(rangeTracker)
21 , m_QuantizedNetwork(INetwork::Create())
22 , m_QuantizationScheme(quantizationScheme)
23 , m_PreserveType(preserveType)
24 {
25 }
26
SetQuantizedInputConnections(const IConnectableLayer * srcLayer,IConnectableLayer * quantizedLayer)27 void QuantizerVisitor::SetQuantizedInputConnections(const IConnectableLayer* srcLayer,
28 IConnectableLayer* quantizedLayer)
29 {
30 ARMNN_ASSERT(srcLayer);
31 for (unsigned int i = 0; i < srcLayer->GetNumInputSlots(); i++)
32 {
33 const IInputSlot& srcInputSlot = srcLayer->GetInputSlot(i);
34 const InputSlot* inputSlot = PolymorphicDowncast<const InputSlot*>(&srcInputSlot);
35 ARMNN_ASSERT(inputSlot);
36 const OutputSlot* outputSlot = inputSlot->GetConnectedOutputSlot();
37
38 ARMNN_ASSERT(outputSlot);
39 unsigned int slotIdx = outputSlot->CalculateIndexOnOwner();
40 Layer& layerToFind = outputSlot->GetOwningLayer();
41
42 auto found = m_OriginalToQuantizedGuidMap.find(layerToFind.GetGuid());
43 if (found == m_OriginalToQuantizedGuidMap.end())
44 {
45 // Error in graph traversal order
46 ARMNN_ASSERT_MSG(false, "Error in graph traversal");
47 return;
48 }
49
50 // Connect the slots in the quantized model
51 IConnectableLayer* prevQuantizedLayer = m_QuantizedGuidToLayerMap[found->second];
52 IInputSlot& newInputSlot = quantizedLayer->GetInputSlot(i);
53 IOutputSlot& newOutputSlot = prevQuantizedLayer->GetOutputSlot(slotIdx);
54 newOutputSlot.Connect(newInputSlot);
55
56 // Fetch the min/max ranges that were computed earlier
57 auto range = m_Ranges.GetRange(layerToFind.GetGuid(), slotIdx);
58 OffsetScalePair qParams = m_QuantizationScheme->ComputeScheme(range.first, range.second);
59
60 // Set the quantization params
61 TensorInfo info(outputSlot->GetTensorInfo());
62 info.SetDataType(m_QuantizationScheme->GetDataType());
63 info.SetQuantizationOffset(qParams.second);
64 info.SetQuantizationScale(qParams.first);
65 newOutputSlot.SetTensorInfo(info);
66 }
67 }
68
CreateQuantizedBias(const IConnectableLayer * srcLayer,const ConstTensor & weights,const Optional<ConstTensor> & biases,std::vector<int32_t> & backing)69 ConstTensor QuantizerVisitor::CreateQuantizedBias(const IConnectableLayer* srcLayer,
70 const ConstTensor& weights,
71 const Optional<ConstTensor>& biases,
72 std::vector<int32_t>& backing)
73 {
74 ARMNN_ASSERT(srcLayer);
75 const IInputSlot& srcInputSlot = srcLayer->GetInputSlot(0);
76 auto inputSlot = PolymorphicDowncast<const InputSlot*>(&srcInputSlot);
77 ARMNN_ASSERT(inputSlot);
78 const OutputSlot* outputSlot = inputSlot->GetConnectedOutputSlot();
79
80 ARMNN_ASSERT(outputSlot);
81 unsigned int slotIdx = outputSlot->CalculateIndexOnOwner();
82 Layer& layerToFind = outputSlot->GetOwningLayer();
83
84 auto found = m_OriginalToQuantizedGuidMap.find(layerToFind.GetGuid());
85 if (found == m_OriginalToQuantizedGuidMap.end())
86 {
87 // Error in graph traversal order
88 ARMNN_ASSERT_MSG(false, "Error in graph traversal");
89 return biases.value();
90 }
91
92 // Fetch the min/max ranges that were computed earlier
93 auto range = m_Ranges.GetRange(layerToFind.GetGuid(), slotIdx);
94 OffsetScalePair qParams = m_QuantizationScheme->ComputeScheme(range.first, range.second);
95
96 // Get the quantization scale based on input and weight scale
97 float scale = qParams.first * weights.GetInfo().GetQuantizationScale();
98
99 // Set up quantized bias tensor info and allocate space
100 TensorInfo qInfo(biases.value().GetInfo().GetShape(), DataType::Signed32, scale, 0);
101 backing.resize(biases.value().GetInfo().GetNumElements());
102
103 // Convert values to int32
104 for (size_t i = 0; i < backing.size(); ++i)
105 {
106 float fp32Value = static_cast<const float*>(biases.value().GetMemoryArea())[i];
107 backing[i] = armnn::numeric_cast<int32_t>(fp32Value * ( 1 / scale ));
108 }
109
110 return ConstTensor(qInfo, backing);
111 }
112
RecordLayer(const IConnectableLayer * srcLayer,IConnectableLayer * quantizedLayer)113 void QuantizerVisitor::RecordLayer(const IConnectableLayer* srcLayer, IConnectableLayer* quantizedLayer)
114 {
115 m_OriginalToQuantizedGuidMap.insert(std::make_pair(srcLayer->GetGuid(), quantizedLayer->GetGuid()));
116 m_QuantizedGuidToLayerMap.insert(std::make_pair(quantizedLayer->GetGuid(), quantizedLayer));
117 }
118
VisitAbsLayer(const IConnectableLayer * layer,const char * name)119 void QuantizerVisitor::VisitAbsLayer(const IConnectableLayer* layer, const char* name)
120 {
121 VisitElementwiseUnaryLayer(layer, ElementwiseUnaryDescriptor(UnaryOperation::Abs), name);
122 }
123
VisitActivationLayer(const IConnectableLayer * layer,const ActivationDescriptor & activationDescriptor,const char * name)124 void QuantizerVisitor::VisitActivationLayer(const IConnectableLayer* layer,
125 const ActivationDescriptor& activationDescriptor,
126 const char* name)
127 {
128 IConnectableLayer* newLayer = m_QuantizedNetwork->AddActivationLayer(activationDescriptor, name);
129 RecordLayer(layer, newLayer);
130 SetQuantizedInputConnections(layer, newLayer);
131 }
132
VisitAdditionLayer(const IConnectableLayer * layer,const char * name)133 void QuantizerVisitor::VisitAdditionLayer(const IConnectableLayer* layer, const char* name)
134 {
135 IConnectableLayer* newLayer = m_QuantizedNetwork->AddAdditionLayer(name);
136 RecordLayer(layer, newLayer);
137 SetQuantizedInputConnections(layer, newLayer);
138 }
139
VisitArgMinMaxLayer(const IConnectableLayer * layer,const ArgMinMaxDescriptor & argMinMaxDescriptor,const char * name)140 void QuantizerVisitor::VisitArgMinMaxLayer(const IConnectableLayer* layer,
141 const ArgMinMaxDescriptor& argMinMaxDescriptor,
142 const char* name)
143 {
144 IConnectableLayer* newLayer = m_QuantizedNetwork->AddArgMinMaxLayer(argMinMaxDescriptor, name);
145 RecordLayer(layer, newLayer);
146 SetQuantizedInputConnections(layer, newLayer);
147 }
148
VisitBatchNormalizationLayer(const IConnectableLayer * layer,const BatchNormalizationDescriptor & desc,const ConstTensor & mean,const ConstTensor & variance,const ConstTensor & beta,const ConstTensor & gamma,const char * name)149 void QuantizerVisitor::VisitBatchNormalizationLayer(const IConnectableLayer* layer,
150 const BatchNormalizationDescriptor& desc,
151 const ConstTensor& mean,
152 const ConstTensor& variance,
153 const ConstTensor& beta,
154 const ConstTensor& gamma,
155 const char* name)
156 {
157 std::vector<uint8_t> meanBacking;
158 ConstTensor qMean = CreateQuantizedConst(mean, meanBacking);
159
160 std::vector<uint8_t> varianceBacking;
161 ConstTensor qVariance = CreateQuantizedConst(variance, varianceBacking);
162
163 std::vector<uint8_t> betaBacking;
164 ConstTensor qBeta = CreateQuantizedConst(beta, betaBacking);
165
166 std::vector<uint8_t> gammaBacking;
167 ConstTensor qGamma = CreateQuantizedConst(gamma, gammaBacking);
168
169 IConnectableLayer* newLayer = m_QuantizedNetwork->AddBatchNormalizationLayer(desc,
170 qMean,
171 qVariance,
172 qBeta,
173 qGamma,
174 name);
175
176 RecordLayer(layer, newLayer);
177 SetQuantizedInputConnections(layer, newLayer);
178 }
179
VisitBatchToSpaceNdLayer(const IConnectableLayer * layer,const BatchToSpaceNdDescriptor & batchToSpaceNdDescriptor,const char * name)180 void QuantizerVisitor::VisitBatchToSpaceNdLayer(const IConnectableLayer* layer,
181 const BatchToSpaceNdDescriptor& batchToSpaceNdDescriptor,
182 const char* name)
183 {
184 IConnectableLayer* newLayer = m_QuantizedNetwork->AddBatchToSpaceNdLayer(batchToSpaceNdDescriptor, name);
185 RecordLayer(layer, newLayer);
186 SetQuantizedInputConnections(layer, newLayer);
187 }
188
VisitComparisonLayer(const IConnectableLayer * layer,const ComparisonDescriptor & comparisonDescriptor,const char * name)189 void QuantizerVisitor::VisitComparisonLayer(const IConnectableLayer* layer,
190 const ComparisonDescriptor& comparisonDescriptor,
191 const char* name)
192 {
193 IConnectableLayer* newLayer = m_QuantizedNetwork->AddComparisonLayer(comparisonDescriptor, name);
194 RecordLayer(layer, newLayer);
195 SetQuantizedInputConnections(layer, newLayer);
196 }
197
VisitConcatLayer(const IConnectableLayer * layer,const OriginsDescriptor & originsDescriptor,const char * name)198 void QuantizerVisitor::VisitConcatLayer(const IConnectableLayer* layer,
199 const OriginsDescriptor& originsDescriptor,
200 const char* name)
201 {
202 IConnectableLayer* newLayer = m_QuantizedNetwork->AddConcatLayer(originsDescriptor, name);
203 RecordLayer(layer, newLayer);
204 SetQuantizedInputConnections(layer, newLayer);
205 }
206
VisitConstantLayer(const IConnectableLayer * layer,const ConstTensor & input,const char * name)207 void QuantizerVisitor::VisitConstantLayer(const IConnectableLayer* layer,
208 const ConstTensor& input,
209 const char* name)
210 {
211 std::vector<uint8_t> inputBacking;
212 ConstTensor qInput = CreateQuantizedConst(input, inputBacking);
213
214 IConnectableLayer* newLayer = m_QuantizedNetwork->AddConstantLayer(qInput, name);
215 RecordLayer(layer, newLayer);
216 }
217
VisitConvolution2dLayer(const IConnectableLayer * layer,const Convolution2dDescriptor & convolution2dDescriptor,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name)218 void QuantizerVisitor::VisitConvolution2dLayer(const IConnectableLayer* layer,
219 const Convolution2dDescriptor& convolution2dDescriptor,
220 const ConstTensor& weights,
221 const Optional<ConstTensor>& biases,
222 const char* name)
223 {
224 std::vector<uint8_t> weightsBacking;
225 ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
226 Optional<ConstTensor> optionalQBiases;
227 std::vector<int32_t> biasesBacking;
228
229 if (biases.has_value())
230 {
231 ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
232 optionalQBiases = Optional<ConstTensor>(qBiases);
233 }
234
235 IConnectableLayer* newLayer = m_QuantizedNetwork->AddConvolution2dLayer(convolution2dDescriptor,
236 qWeights,
237 optionalQBiases,
238 name);
239
240 RecordLayer(layer, newLayer);
241 SetQuantizedInputConnections(layer, newLayer);
242 }
243
VisitDepthToSpaceLayer(const IConnectableLayer * layer,const DepthToSpaceDescriptor & descriptor,const char * name)244 void QuantizerVisitor::VisitDepthToSpaceLayer(const IConnectableLayer* layer,
245 const DepthToSpaceDescriptor& descriptor,
246 const char* name)
247 {
248 IConnectableLayer* newLayer = m_QuantizedNetwork->AddDepthToSpaceLayer(descriptor, name);
249 RecordLayer(layer, newLayer);
250 SetQuantizedInputConnections(layer, newLayer);
251 }
252
VisitDepthwiseConvolution2dLayer(const IConnectableLayer * layer,const DepthwiseConvolution2dDescriptor & desc,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name)253 void QuantizerVisitor::VisitDepthwiseConvolution2dLayer(const IConnectableLayer* layer,
254 const DepthwiseConvolution2dDescriptor& desc,
255 const ConstTensor& weights,
256 const Optional<ConstTensor>& biases,
257 const char* name)
258 {
259 std::vector<uint8_t> weightsBacking;
260 ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
261 Optional<ConstTensor> optionalQBiases;
262 std::vector<int32_t> biasesBacking;
263
264 if (biases.has_value())
265 {
266 ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
267 optionalQBiases = Optional<ConstTensor>(qBiases);
268 }
269
270 IConnectableLayer* newLayer = m_QuantizedNetwork->AddDepthwiseConvolution2dLayer(desc,
271 qWeights,
272 optionalQBiases,
273 name);
274
275 RecordLayer(layer, newLayer);
276 SetQuantizedInputConnections(layer, newLayer);
277 }
278
VisitElementwiseUnaryLayer(const IConnectableLayer * layer,const ElementwiseUnaryDescriptor & elementwiseUnaryDescriptor,const char * name)279 void QuantizerVisitor::VisitElementwiseUnaryLayer(const IConnectableLayer* layer,
280 const ElementwiseUnaryDescriptor& elementwiseUnaryDescriptor,
281 const char* name)
282 {
283 IConnectableLayer* newLayer = m_QuantizedNetwork->AddElementwiseUnaryLayer(elementwiseUnaryDescriptor, name);
284 RecordLayer(layer, newLayer);
285 SetQuantizedInputConnections(layer, newLayer);
286 }
287
VisitFillLayer(const IConnectableLayer * layer,const FillDescriptor & desc,const char * name)288 void QuantizerVisitor::VisitFillLayer(const IConnectableLayer* layer,
289 const FillDescriptor& desc,
290 const char* name)
291 {
292 IConnectableLayer* newLayer = m_QuantizedNetwork->AddFillLayer(desc, name);
293 RecordLayer(layer, newLayer);
294 SetQuantizedInputConnections(layer, newLayer);
295 }
296
VisitFullyConnectedLayer(const IConnectableLayer * layer,const FullyConnectedDescriptor & desc,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name)297 void QuantizerVisitor::VisitFullyConnectedLayer(const IConnectableLayer *layer,
298 const FullyConnectedDescriptor& desc,
299 const ConstTensor& weights,
300 const Optional<ConstTensor>& biases,
301 const char *name)
302 {
303 std::vector<uint8_t> weightsBacking;
304 ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
305 Optional<ConstTensor> optionalQBiases;
306 std::vector<int32_t> biasesBacking;
307
308 if (biases.has_value())
309 {
310 ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
311 optionalQBiases = Optional<ConstTensor>(qBiases);
312 }
313
314 IConnectableLayer* newLayer = m_QuantizedNetwork->AddFullyConnectedLayer(desc,
315 qWeights,
316 optionalQBiases,
317 name);
318
319 RecordLayer(layer, newLayer);
320 SetQuantizedInputConnections(layer, newLayer);
321 }
322
VisitInputLayer(const IConnectableLayer * layer,LayerBindingId id,const char * name)323 void QuantizerVisitor::VisitInputLayer(const IConnectableLayer *layer, LayerBindingId id, const char *name)
324 {
325 const DataType dataType = layer->GetOutputSlot(0).GetTensorInfo().GetDataType();
326 IConnectableLayer* inputLayer = m_QuantizedNetwork->AddInputLayer(id, name);
327
328 if (m_PreserveType && (dataType == DataType::Float32 || dataType == DataType::Float16))
329 {
330 IConnectableLayer* quantizeLayer = m_QuantizedNetwork->AddQuantizeLayer();
331 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
332 inputLayer->GetOutputSlot(0).SetTensorInfo(layer->GetOutputSlot(0).GetTensorInfo());
333 RecordLayer(layer, quantizeLayer);
334 }
335 else
336 {
337 RecordLayer(layer, inputLayer);
338 }
339 }
340
VisitInstanceNormalizationLayer(const IConnectableLayer * layer,const InstanceNormalizationDescriptor & descriptor,const char * name)341 void QuantizerVisitor::VisitInstanceNormalizationLayer(const IConnectableLayer* layer,
342 const InstanceNormalizationDescriptor& descriptor,
343 const char* name)
344 {
345 IConnectableLayer* newLayer = m_QuantizedNetwork->AddInstanceNormalizationLayer(descriptor, name);
346 RecordLayer(layer, newLayer);
347 SetQuantizedInputConnections(layer, newLayer);
348 }
349
VisitLogSoftmaxLayer(const IConnectableLayer * layer,const LogSoftmaxDescriptor & logSoftmaxDescriptor,const char * name)350 void QuantizerVisitor::VisitLogSoftmaxLayer(const IConnectableLayer* layer,
351 const LogSoftmaxDescriptor& logSoftmaxDescriptor,
352 const char* name)
353 {
354 IConnectableLayer* newLayer = m_QuantizedNetwork->AddLogSoftmaxLayer(logSoftmaxDescriptor, name);
355 RecordLayer(layer, newLayer);
356 SetQuantizedInputConnections(layer, newLayer);
357 }
358
VisitMeanLayer(const IConnectableLayer * layer,const MeanDescriptor & meanDescriptor,const char * name)359 void QuantizerVisitor::VisitMeanLayer(const IConnectableLayer* layer,
360 const MeanDescriptor& meanDescriptor,
361 const char* name)
362 {
363 IConnectableLayer* newLayer = m_QuantizedNetwork->AddMeanLayer(meanDescriptor, name);
364 RecordLayer(layer, newLayer);
365 SetQuantizedInputConnections(layer, newLayer);
366 }
367
VisitMultiplicationLayer(const IConnectableLayer * layer,const char * name)368 void QuantizerVisitor::VisitMultiplicationLayer(const IConnectableLayer* layer,
369 const char* name)
370 {
371 IConnectableLayer* newLayer = m_QuantizedNetwork->AddMultiplicationLayer(name);
372 RecordLayer(layer, newLayer);
373 SetQuantizedInputConnections(layer, newLayer);
374 }
375
VisitNormalizationLayer(const armnn::IConnectableLayer * layer,const armnn::NormalizationDescriptor & normalizationDescriptor,const char * name)376 void QuantizerVisitor::VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
377 const armnn::NormalizationDescriptor& normalizationDescriptor,
378 const char* name)
379 {
380 IConnectableLayer* newLayer = m_QuantizedNetwork->AddNormalizationLayer(normalizationDescriptor, name);
381 RecordLayer(layer, newLayer);
382 SetQuantizedInputConnections(layer, newLayer);
383 }
384
VisitOutputLayer(const IConnectableLayer * layer,LayerBindingId id,const char * name)385 void QuantizerVisitor::VisitOutputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name)
386 {
387 const TensorInfo& info = layer->GetInputSlot(0).GetConnection()->GetTensorInfo();
388 const DataType& dataType = info.GetDataType();
389 IConnectableLayer* outputLayer = m_QuantizedNetwork->AddOutputLayer(id, name);
390
391 if (m_PreserveType && (dataType == DataType::Float32 || dataType == DataType::Float16))
392 {
393 IConnectableLayer* dequantizeLayer = m_QuantizedNetwork->AddDequantizeLayer();
394 RecordLayer(layer, dequantizeLayer);
395 SetQuantizedInputConnections(layer, dequantizeLayer);
396 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
397 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
398 }
399 else
400 {
401 RecordLayer(layer, outputLayer);
402 SetQuantizedInputConnections(layer, outputLayer);
403 }
404 }
405
VisitPadLayer(const IConnectableLayer * layer,const PadDescriptor & padDescriptor,const char * name)406 void QuantizerVisitor::VisitPadLayer(const IConnectableLayer* layer,
407 const PadDescriptor& padDescriptor,
408 const char* name)
409 {
410 IConnectableLayer* newLayer = m_QuantizedNetwork->AddPadLayer(padDescriptor, name);
411 RecordLayer(layer, newLayer);
412 SetQuantizedInputConnections(layer, newLayer);
413 }
414
VisitPermuteLayer(const IConnectableLayer * layer,const PermuteDescriptor & permuteDescriptor,const char * name)415 void QuantizerVisitor::VisitPermuteLayer(const IConnectableLayer* layer,
416 const PermuteDescriptor& permuteDescriptor,
417 const char* name)
418 {
419 IConnectableLayer* newLayer = m_QuantizedNetwork->AddPermuteLayer(permuteDescriptor, name);
420 RecordLayer(layer, newLayer);
421 SetQuantizedInputConnections(layer, newLayer);
422 }
423
VisitPooling2dLayer(const IConnectableLayer * layer,const Pooling2dDescriptor & pooling2dDescriptor,const char * name)424 void QuantizerVisitor::VisitPooling2dLayer(const IConnectableLayer* layer,
425 const Pooling2dDescriptor& pooling2dDescriptor,
426 const char* name)
427 {
428 IConnectableLayer* newLayer = m_QuantizedNetwork->AddPooling2dLayer(pooling2dDescriptor, name);
429 RecordLayer(layer, newLayer);
430 SetQuantizedInputConnections(layer, newLayer);
431 }
432
VisitPreluLayer(const IConnectableLayer * layer,const char * name)433 void QuantizerVisitor::VisitPreluLayer(const IConnectableLayer* layer,
434 const char* name)
435 {
436 IConnectableLayer* newLayer = m_QuantizedNetwork->AddPreluLayer(name);
437 RecordLayer(layer, newLayer);
438 SetQuantizedInputConnections(layer, newLayer);
439 }
440
VisitReshapeLayer(const IConnectableLayer * layer,const ReshapeDescriptor & reshapeDescriptor,const char * name)441 void QuantizerVisitor::VisitReshapeLayer(const IConnectableLayer* layer,
442 const ReshapeDescriptor& reshapeDescriptor,
443 const char* name)
444 {
445 IConnectableLayer* newLayer = m_QuantizedNetwork->AddReshapeLayer(reshapeDescriptor, name);
446 RecordLayer(layer, newLayer);
447 SetQuantizedInputConnections(layer, newLayer);
448 }
449
VisitResizeBilinearLayer(const IConnectableLayer * layer,const ResizeBilinearDescriptor & resizeBilinearDescriptor,const char * name)450 void QuantizerVisitor::VisitResizeBilinearLayer(const IConnectableLayer* layer,
451 const ResizeBilinearDescriptor& resizeBilinearDescriptor,
452 const char* name)
453 {
454 ResizeDescriptor resizeDescriptor;
455 resizeDescriptor.m_Method = ResizeMethod::Bilinear;
456 resizeDescriptor.m_TargetWidth = resizeBilinearDescriptor.m_TargetWidth;
457 resizeDescriptor.m_TargetHeight = resizeBilinearDescriptor.m_TargetHeight;
458 resizeDescriptor.m_DataLayout = resizeBilinearDescriptor.m_DataLayout;
459
460 VisitResizeLayer(layer, resizeDescriptor, name);
461 }
462
VisitResizeLayer(const IConnectableLayer * layer,const ResizeDescriptor & resizeDescriptor,const char * name)463 void QuantizerVisitor::VisitResizeLayer(const IConnectableLayer* layer,
464 const ResizeDescriptor& resizeDescriptor,
465 const char* name)
466 {
467 IConnectableLayer* newLayer = m_QuantizedNetwork->AddResizeLayer(resizeDescriptor, name);
468 RecordLayer(layer, newLayer);
469 SetQuantizedInputConnections(layer, newLayer);
470 }
471
VisitRsqrtLayer(const IConnectableLayer * layer,const char * name)472 void QuantizerVisitor::VisitRsqrtLayer(const IConnectableLayer* layer, const char* name)
473 {
474 VisitElementwiseUnaryLayer(layer, ElementwiseUnaryDescriptor(UnaryOperation::Rsqrt), name);
475 }
476
VisitSliceLayer(const IConnectableLayer * layer,const SliceDescriptor & sliceDescriptor,const char * name)477 void QuantizerVisitor::VisitSliceLayer(const IConnectableLayer* layer,
478 const SliceDescriptor& sliceDescriptor,
479 const char* name)
480 {
481 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSliceLayer(sliceDescriptor, name);
482 RecordLayer(layer, newLayer);
483 SetQuantizedInputConnections(layer, newLayer);
484 }
485
VisitSoftmaxLayer(const IConnectableLayer * layer,const SoftmaxDescriptor & softmaxDescriptor,const char * name)486 void QuantizerVisitor::VisitSoftmaxLayer(const IConnectableLayer* layer,
487 const SoftmaxDescriptor& softmaxDescriptor,
488 const char* name)
489 {
490 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSoftmaxLayer(softmaxDescriptor, name);
491 RecordLayer(layer, newLayer);
492 SetQuantizedInputConnections(layer, newLayer);
493 }
494
VisitSpaceToBatchNdLayer(const IConnectableLayer * layer,const SpaceToBatchNdDescriptor & spaceToBatchNdDescriptor,const char * name)495 void QuantizerVisitor::VisitSpaceToBatchNdLayer(const IConnectableLayer* layer,
496 const SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
497 const char* name)
498 {
499 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSpaceToBatchNdLayer(spaceToBatchNdDescriptor, name);
500 RecordLayer(layer, newLayer);
501 SetQuantizedInputConnections(layer, newLayer);
502 }
503
VisitSpaceToDepthLayer(const IConnectableLayer * layer,const SpaceToDepthDescriptor & spaceToDepthDescriptor,const char * name)504 void QuantizerVisitor::VisitSpaceToDepthLayer(const IConnectableLayer* layer,
505 const SpaceToDepthDescriptor& spaceToDepthDescriptor,
506 const char* name)
507 {
508 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSpaceToDepthLayer(spaceToDepthDescriptor, name);
509 RecordLayer(layer, newLayer);
510 SetQuantizedInputConnections(layer, newLayer);
511 }
512
VisitSplitterLayer(const IConnectableLayer * layer,const SplitterDescriptor & splitterDescriptor,const char * name)513 void QuantizerVisitor::VisitSplitterLayer(const IConnectableLayer* layer,
514 const SplitterDescriptor& splitterDescriptor,
515 const char* name)
516 {
517 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSplitterLayer(splitterDescriptor, name);
518 RecordLayer(layer, newLayer);
519 SetQuantizedInputConnections(layer, newLayer);
520 }
521
VisitStackLayer(const IConnectableLayer * layer,const StackDescriptor & stackDescriptor,const char * name)522 void QuantizerVisitor::VisitStackLayer(const IConnectableLayer* layer,
523 const StackDescriptor& stackDescriptor,
524 const char* name)
525 {
526 IConnectableLayer* newLayer = m_QuantizedNetwork->AddStackLayer(stackDescriptor, name);
527 RecordLayer(layer, newLayer);
528 SetQuantizedInputConnections(layer, newLayer);
529 }
530
VisitStridedSliceLayer(const IConnectableLayer * layer,const StridedSliceDescriptor & stridedSliceDescriptor,const char * name)531 void QuantizerVisitor::VisitStridedSliceLayer(const IConnectableLayer* layer,
532 const StridedSliceDescriptor& stridedSliceDescriptor,
533 const char* name)
534 {
535 IConnectableLayer* newLayer = m_QuantizedNetwork->AddStridedSliceLayer(stridedSliceDescriptor, name);
536 RecordLayer(layer, newLayer);
537 SetQuantizedInputConnections(layer, newLayer);
538 }
539
VisitSubtractionLayer(const IConnectableLayer * layer,const char * name)540 void QuantizerVisitor::VisitSubtractionLayer(const IConnectableLayer* layer,
541 const char* name)
542 {
543 IConnectableLayer* newLayer = m_QuantizedNetwork->AddSubtractionLayer(name);
544 RecordLayer(layer, newLayer);
545 SetQuantizedInputConnections(layer, newLayer);
546 }
547
VisitTransposeConvolution2dLayer(const IConnectableLayer * layer,const TransposeConvolution2dDescriptor & descriptor,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name)548 void QuantizerVisitor::VisitTransposeConvolution2dLayer(const IConnectableLayer* layer,
549 const TransposeConvolution2dDescriptor& descriptor,
550 const ConstTensor& weights,
551 const Optional<ConstTensor>& biases,
552 const char* name)
553 {
554 // quantize weights
555 std::vector<uint8_t> weightsBacking;
556 ConstTensor qWeights = CreateQuantizedConst(weights, weightsBacking);
557
558 // quantize biases
559 std::vector<int32_t> biasesBacking;
560 Optional<ConstTensor> optionalQBiases;
561 if (biases.has_value())
562 {
563 ConstTensor qBiases = CreateQuantizedBias(layer, qWeights, biases, biasesBacking);
564 optionalQBiases = Optional<ConstTensor>(qBiases);
565 }
566
567 IConnectableLayer* newLayer = m_QuantizedNetwork->AddTransposeConvolution2dLayer(descriptor,
568 qWeights,
569 optionalQBiases,
570 name);
571
572 RecordLayer(layer, newLayer);
573 SetQuantizedInputConnections(layer, newLayer);
574 }
575
VisitTransposeLayer(const IConnectableLayer * layer,const TransposeDescriptor & transposeDescriptor,const char * name)576 void QuantizerVisitor::VisitTransposeLayer(const IConnectableLayer* layer,
577 const TransposeDescriptor& transposeDescriptor,
578 const char* name)
579 {
580 IConnectableLayer* newLayer = m_QuantizedNetwork->AddTransposeLayer(transposeDescriptor, name);
581 RecordLayer(layer, newLayer);
582 SetQuantizedInputConnections(layer, newLayer);
583 }
584
585 } //namespace armnn
586