• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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