ArmNN
 22.11
armnn_driver Namespace Reference

Helper classes. More...

Classes

class  ArmnnDevice
 
class  ArmnnDriver
 
class  ArmnnDriverImpl
 
class  ArmnnPreparedModel
 
struct  CanonicalExecutionContext
 
class  ConstTensorPin
 
struct  ConversionData
 
class  Converter
 
class  DriverOptions
 
class  LayerInputHandle
 
class  ModelToINetworkTransformer
 
class  UnsupportedOperand
 

Typedefs

template<typename TensorType >
using DumpElementFunction = void(*)(const TensorType &tensor, unsigned int elementIndex, std::ofstream &fileStream)
 
using Model = ::android::nn::Model
 Helper classes. More...
 
using Operand = ::android::nn::Operand
 
using OperandLifeTime = ::android::nn::Operand::LifeTime
 
using OperandType = ::android::nn::OperandType
 
using Operation = ::android::nn::Operation
 
using OperationType = ::android::nn::OperationType
 
using ErrorStatus = ::android::nn::ErrorStatus
 
using DequantizeResult = std::tuple< std::unique_ptr< float[]>, size_t, armnn::TensorInfo, DequantizeStatus >
 
using Half = half_float::half
 

Enumerations

enum  ConversionResult { Success, ErrorMappingPools, UnsupportedFeature }
 
enum  DequantizeStatus { SUCCESS, NOT_REQUIRED, INVALID_OPERAND }
 

Functions

void SwizzleAndroidNn4dTensorToArmNn (armnn::TensorInfo &tensor, const void *input, void *output, const armnn::PermutationVector &mappings)
 Swizzles tensor data in input according to the dimension mappings. More...
 
void * GetMemoryFromPool (DataLocation location, const std::vector< android::nn::RunTimePoolInfo > &memPools)
 Returns a pointer to a specific location in a pool`. More...
 
void * GetMemoryFromPointer (const Request::Argument &requestArg)
 
armnn::TensorInfo GetTensorInfoForOperand (const Operand &operand)
 
std::string GetOperandSummary (const Operand &operand)
 
template<typename TensorType >
void DumpTensor (const std::string &dumpDir, const std::string &requestName, const std::string &tensorName, const TensorType &tensor)
 
template void DumpTensor< armnn::ConstTensor > (const std::string &dumpDir, const std::string &requestName, const std::string &tensorName, const armnn::ConstTensor &tensor)
 
template void DumpTensor< armnn::Tensor > (const std::string &dumpDir, const std::string &requestName, const std::string &tensorName, const armnn::Tensor &tensor)
 
void DumpJsonProfilingIfRequired (bool gpuProfilingEnabled, const std::string &dumpDir, armnn::NetworkId networkId, const armnn::IProfiler *profiler)
 
std::string ExportNetworkGraphToDotFile (const armnn::IOptimizedNetwork &optimizedNetwork, const std::string &dumpDir)
 
std::string SerializeNetwork (const armnn::INetwork &network, const std::string &dumpDir, std::vector< uint8_t > &dataCacheData, bool dataCachingActive)
 
bool IsDynamicTensor (const armnn::TensorInfo &outputInfo)
 Checks if a tensor info represents a dynamic tensor. More...
 
bool AreDynamicTensorsSupported (void)
 Checks for ArmNN support of dynamic tensors. More...
 
bool isQuantizedOperand (const OperandType &operandType)
 
std::string GetModelSummary (const Model &model)
 
std::string GetFileTimestamp ()
 
void RenameExportedFiles (const std::string &existingSerializedFileName, const std::string &existingDotFileName, const std::string &dumpDir, const armnn::NetworkId networkId)
 
void RenameFile (const std::string &existingName, const std::string &extension, const std::string &dumpDir, const armnn::NetworkId networkId)
 
void CommitPools (std::vector<::android::nn::RunTimePoolInfo > &memPools)
 
OutputShape ComputeShape (const armnn::TensorInfo &info)
 
bool IsWeightsValid (const Operation &operation, uint32_t inputIndex, const Model &model)
 Utility functions. More...
 
ConstTensorPin ConvertOperandToConstTensorPin (const Operand &operand, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings, const armnn::TensorShape *overrideTensorShape, bool optional, const armnn::DataType *overrideDataType)
 
LayerInputHandle ConvertToLayerInputHandle (const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data, const armnn::PermutationVector &dimensionMappings, const LayerInputHandle *inputHandle)
 
bool ConvertPaddings (const Operation &operation, const Model &model, ConversionData &data, unsigned int rank, armnn::PadDescriptor &padDescriptor)
 
bool ConvertPooling2d (const Operation &operation, const char *operationName, armnn::PoolingAlgorithm poolType, const Model &model, ConversionData &data)
 
bool ConvertReduce (const Operation &operation, const Model &model, ConversionData &data, armnn::ReduceOperation reduceOperation)
 
bool ConvertToActivation (const Operation &operation, const char *operationName, const armnn::ActivationDescriptor &activationDesc, const Model &model, ConversionData &data)
 
DequantizeResult DequantizeIfRequired (size_t operand_index, const Operation &operation, const Model &model, const ConversionData &data)
 
ConstTensorPin DequantizeAndMakeConstTensorPin (const Operation &operation, const Model &model, const ConversionData &data, size_t operandIndex, bool optional)
 
bool GetInputPaddingScheme (const Operation &operation, uint32_t inputIndex, PaddingScheme &outPaddingScheme, const Model &model, const ConversionData &data)
 
const void * GetOperandValueReadOnlyAddress (const Operand &operand, const Model &model, const ConversionData &data, bool optional)
 
bool GetTensorInt32Values (const Operand &operand, std::vector< int32_t > &outValues, const Model &model, const ConversionData &data)
 
armnn::DataLayout OptionalDataLayout (const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data)
 
armnn::IConnectableLayerProcessActivation (const armnn::TensorInfo &tensorInfo, ActivationFn activation, armnn::IConnectableLayer *prevLayer, ConversionData &data)
 
bool SetupAndTrackLayerOutputSlot (const Operation &operation, uint32_t operationOutputIndex, armnn::IConnectableLayer &layer, uint32_t layerOutputIndex, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc, const ActivationFn &activationFunction, bool inferOutputShapes)
 
bool IsConnectedToDequantize (armnn::IOutputSlot *ioutputSlot)
 
const OperandGetInputOperand (const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
 
const OperandGetOutputOperand (const Operation &operation, uint32_t outputIndex, const Model &model)
 
bool GetOperandType (const Operation &operation, uint32_t inputIndex, const Model &model, OperandType &type)
 
bool IsOperandConstant (const Operand &operand)
 
ConstTensorPin ConvertOperationInputToConstTensorPin (const Operation &operation, uint32_t inputIndex, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings=g_DontPermute, const armnn::TensorShape *overrideTensorShape=nullptr, bool optional=false)
 
template<typename OutputType >
bool GetInputScalar (const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)
 
bool GetInputInt32 (const Operation &operation, uint32_t inputIndex, int32_t &outValue, const Model &model, const ConversionData &data)
 
bool GetInputFloat32 (const Operation &operation, uint32_t inputIndex, float &outValue, const Model &model, const ConversionData &data)
 
bool GetInputActivationFunctionImpl (const Operation &operation, uint32_t inputIndex, OperandType type, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
 
bool GetInputActivationFunction (const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
 
bool GetInputActivationFunctionFromTensor (const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
 
bool GetOptionalInputActivation (const Operation &operation, uint32_t inputIndex, ActivationFn &activationFunction, const Model &model, const ConversionData &data)
 
template<typename ConvolutionDescriptor >
bool GetOptionalConvolutionDilationParams (const Operation &operation, uint32_t dilationXIndex, ConvolutionDescriptor &descriptor, const Model &model, const ConversionData &data)
 
bool GetOptionalBool (const Operation &operation, uint32_t inputIndex, const Model &model, const ConversionData &data)
 
bool SetupAndTrackLayerOutputSlot (const Operation &operation, uint32_t outputIndex, armnn::IConnectableLayer &layer, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo=nullptr, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc=nullptr, const ActivationFn &activationFunction=ActivationFn::kActivationNone)
 
bool IsQSymm8 (const Operand &operand)
 

Variables

const armnn::PermutationVector g_DontPermute {}
 

Detailed Description

Helper classes.

Typedef Documentation

◆ DequantizeResult

using DequantizeResult = std::tuple<std::unique_ptr<float[]>, size_t, armnn::TensorInfo, DequantizeStatus>

Definition at line 1004 of file ConversionUtils.hpp.

◆ DumpElementFunction

using DumpElementFunction = void (*)(const TensorType& tensor, unsigned int elementIndex, std::ofstream& fileStream)

Definition at line 204 of file CanonicalUtils.cpp.

◆ ErrorStatus

using ErrorStatus = ::android::nn::ErrorStatus

Definition at line 49 of file ConversionUtils.hpp.

◆ Half

using Half = half_float::half

Definition at line 14 of file Converter.cpp.

◆ Model

using Model = ::android::nn::Model

Helper classes.

Definition at line 43 of file ConversionUtils.hpp.

◆ Operand

using Operand = ::android::nn::Operand

Definition at line 44 of file ConversionUtils.hpp.

◆ OperandLifeTime

using OperandLifeTime = ::android::nn::Operand::LifeTime

Definition at line 45 of file ConversionUtils.hpp.

◆ OperandType

using OperandType = ::android::nn::OperandType

Definition at line 46 of file ConversionUtils.hpp.

◆ Operation

using Operation = ::android::nn::Operation

Definition at line 47 of file ConversionUtils.hpp.

◆ OperationType

using OperationType = ::android::nn::OperationType

Definition at line 48 of file ConversionUtils.hpp.

Enumeration Type Documentation

◆ ConversionResult

enum ConversionResult
strong
Enumerator
Success 
ErrorMappingPools 
UnsupportedFeature 

Definition at line 125 of file ConversionUtils.hpp.

◆ DequantizeStatus

enum DequantizeStatus
strong
Enumerator
SUCCESS 
NOT_REQUIRED 
INVALID_OPERAND 

Definition at line 997 of file ConversionUtils.hpp.

Function Documentation

◆ AreDynamicTensorsSupported()

bool AreDynamicTensorsSupported ( )

Checks for ArmNN support of dynamic tensors.

Definition at line 500 of file CanonicalUtils.cpp.

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), and ConvertToActivation().

501 {
502  return true;
503 }

◆ CommitPools()

void CommitPools ( std::vector<::android::nn::RunTimePoolInfo > &  memPools)

Definition at line 610 of file CanonicalUtils.cpp.

Referenced by ComputeShape(), and ArmnnPreparedModel::ExecuteGraph().

611 {
612  // Commit output buffers.
613  // Note that we update *all* pools, even if they aren't actually used as outputs -
614  // this is simpler and is what the CpuExecutor does.
615  for (auto& pool : memPools)
616  {
617  // Type android::nn::RunTimePoolInfo has changed between Android P & Q and Android R, where
618  // update() has been removed and flush() added.
619  pool.flush();
620  }
621 }

◆ ComputeShape()

OutputShape armnn_driver::ComputeShape ( const armnn::TensorInfo info)
inline

Definition at line 95 of file CanonicalUtils.hpp.

References CommitPools(), TensorShape::GetDimensionality(), TensorShape::GetNumDimensions(), TensorInfo::GetShape(), and armnn::Scalar.

Referenced by ArmnnPreparedModel::ArmnnPreparedModel(), and ArmnnPreparedModel::execute().

96 {
97  OutputShape shape;
98 
99  armnn::TensorShape tensorShape = info.GetShape();
100  // Android will expect scalars as a zero dimensional tensor
102  {
103  shape.dimensions = std::vector<uint32_t>{};
104  }
105  else
106  {
107  std::vector<uint32_t> dimensions;
108  const unsigned int numDims = tensorShape.GetNumDimensions();
109  dimensions.resize(numDims);
110  for (unsigned int outputIdx = 0u; outputIdx < numDims; ++outputIdx)
111  {
112  dimensions[outputIdx] = tensorShape[outputIdx];
113  }
114  shape.dimensions = dimensions;
115  }
116 
117  shape.isSufficient = true;
118 
119  return shape;
120 }
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
Dimensionality GetDimensionality() const
Function that returns the tensor type.
Definition: Tensor.hpp:92
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174

◆ ConvertOperandToConstTensorPin()

ConstTensorPin ConvertOperandToConstTensorPin ( const Operand operand,
const Model model,
const ConversionData data,
const armnn::PermutationVector dimensionMappings,
const armnn::TensorShape overrideTensorShape,
bool  optional,
const armnn::DataType overrideDataType 
)

Definition at line 154 of file ConversionUtils.cpp.

References ConstTensorPin::ConstTensorPin(), GetOperandValueReadOnlyAddress(), GetTensorInfoForOperand(), IsOperandConstant(), TensorInfo::SetConstant(), TensorInfo::SetDataType(), and TensorInfo::SetShape().

Referenced by ConvertOperationInputToConstTensorPin(), ConvertToLayerInputHandle(), and IsOperandConstant().

161 {
162  if (!IsOperandTypeSupportedForTensors(operand.type))
163  {
164  VLOG(DRIVER) << __func__ << ": unsupported operand type for tensor" << operand.type;
165  return ConstTensorPin();
166  }
167 
168  if (!optional && !IsOperandConstant(operand))
169  {
170  VLOG(DRIVER) << __func__ << ": lifetime for input tensor: r" << operand.lifetime;
171  return ConstTensorPin();
172  }
173 
174  const void* const valueStart = GetOperandValueReadOnlyAddress(operand, model, data, optional);
175  if (!valueStart)
176  {
177  if (optional)
178  {
179  // optional tensor with no values is not really an error; return it as invalid, but marked as optional
180  return ConstTensorPin(true);
181  }
182  // mandatory tensor with no values
183  Fail("%s: failed to get operand address", __func__);
184  return ConstTensorPin();
185  }
186 
187  armnn::TensorInfo tensorInfo = GetTensorInfoForOperand(operand);
188 
189  if (overrideTensorShape)
190  {
191  tensorInfo.SetShape(*overrideTensorShape);
192  }
193 
194  if (overrideDataType)
195  {
196  tensorInfo.SetDataType(*overrideDataType);
197  }
198 
199  // Make sure isConstant flag is set.
200  tensorInfo.SetConstant();
201  return ConstTensorPin(tensorInfo, valueStart, operand.location.length, dimensionMappings);
202 }
void SetShape(const TensorShape &newShape)
Definition: Tensor.hpp:193
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
void SetDataType(DataType type)
Definition: Tensor.hpp:199
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:514
bool IsOperandConstant(const Operand &operand)

◆ ConvertOperationInputToConstTensorPin()

ConstTensorPin armnn_driver::ConvertOperationInputToConstTensorPin ( const Operation operation,
uint32_t  inputIndex,
const Model model,
const ConversionData data,
const armnn::PermutationVector dimensionMappings = g_DontPermute,
const armnn::TensorShape overrideTensorShape = nullptr,
bool  optional = false 
)
inline

Definition at line 708 of file ConversionUtils.hpp.

References ConvertOperandToConstTensorPin(), and GetInputOperand().

Referenced by Converter::ConvertOperation(), and DequantizeAndMakeConstTensorPin().

716 {
717  const Operand* operand = GetInputOperand(operation, inputIndex, model);
718  if (!operand)
719  {
720  Fail("%s: failed to get input operand: index=%u", __func__, inputIndex);
721  return ConstTensorPin();
722  }
723  return ConvertOperandToConstTensorPin(*operand,
724  model,
725  data,
726  dimensionMappings,
727  overrideTensorShape,
728  optional);
729 }
ConstTensorPin ConvertOperandToConstTensorPin(const Operand &operand, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings, const armnn::TensorShape *overrideTensorShape, bool optional, const armnn::DataType *overrideDataType)
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
::android::nn::Operand Operand

◆ ConvertPaddings()

bool ConvertPaddings ( const Operation operation,
const Model model,
ConversionData data,
unsigned int  rank,
armnn::PadDescriptor padDescriptor 
)

Definition at line 334 of file ConversionUtils.cpp.

References GetInputOperand(), TensorShape::GetNumDimensions(), TensorShape::GetNumElements(), GetTensorInt32Values(), and PadDescriptor::m_PadList.

Referenced by Converter::ConvertOperation(), and SetupAndTrackLayerOutputSlot().

339 {
340  const Operand* paddingsOperand = GetInputOperand(operation, 1, model);
341  if (!paddingsOperand)
342  {
343  return Fail("%s: Could not read paddings operand", __func__);
344  }
345 
346  armnn::TensorShape paddingsOperandShape = GetTensorShapeForOperand(*paddingsOperand);
347  if (paddingsOperandShape.GetNumDimensions() != 2 || paddingsOperandShape.GetNumElements() != rank * 2)
348  {
349  return Fail("%s: Operation has invalid paddings operand: expected shape [%d, 2]", __func__, rank);
350  }
351 
352  std::vector<int32_t> paddings;
353  if (!GetTensorInt32Values(*paddingsOperand, paddings, model, data))
354  {
355  return Fail("%s: Operation has invalid or unsupported paddings operand", __func__);
356  }
357 
358  // add padding for each dimension of input tensor.
359  for (unsigned int i = 0; i < paddings.size() - 1; i += 2)
360  {
361  int paddingBeforeInput = paddings[i];
362  int paddingAfterInput = paddings[i + 1];
363 
364  if (paddingBeforeInput < 0 || paddingAfterInput < 0)
365  {
366  return Fail("%s: Operation has invalid paddings operand, invalid padding values.", __func__);
367  }
368 
369  padDescriptor.m_PadList.emplace_back((unsigned int) paddingBeforeInput, (unsigned int) paddingAfterInput);
370  }
371 
372  return true;
373 }
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified...
Definition: Tensor.cpp:181
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
bool GetTensorInt32Values(const Operand &operand, std::vector< int32_t > &outValues, const Model &model, const ConversionData &data)
::android::nn::Operand Operand
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174

◆ ConvertPooling2d()

bool ConvertPooling2d ( const Operation operation,
const char *  operationName,
armnn::PoolingAlgorithm  poolType,
const Model model,
ConversionData data 
)

Definition at line 376 of file ConversionUtils.cpp.

References AreDynamicTensorsSupported(), LayerInputHandle::Connect(), ConvertToLayerInputHandle(), armnn::Floor, FORWARD_LAYER_SUPPORT_FUNC, DataLayoutIndexed::GetHeightIndex(), GetInputActivationFunction(), GetInputPaddingScheme(), GetInputScalar(), IConnectableLayer::GetInputSlot(), GetOutputOperand(), TensorInfo::GetShape(), LayerInputHandle::GetTensorInfo(), GetTensorInfoForOperand(), DataLayoutIndexed::GetWidthIndex(), IsDynamicTensor(), armnn::IsPooling2dSupported(), LayerInputHandle::IsValid(), ConversionData::m_Backends, Pooling2dDescriptor::m_DataLayout, ConversionData::m_Network, Pooling2dDescriptor::m_OutputShapeRounding, Pooling2dDescriptor::m_PadBottom, Pooling2dDescriptor::m_PadLeft, Pooling2dDescriptor::m_PadRight, Pooling2dDescriptor::m_PadTop, Pooling2dDescriptor::m_PoolHeight, Pooling2dDescriptor::m_PoolType, Pooling2dDescriptor::m_PoolWidth, Pooling2dDescriptor::m_StrideX, Pooling2dDescriptor::m_StrideY, armnn::NHWC, OptionalDataLayout(), and SetupAndTrackLayerOutputSlot().

Referenced by Converter::ConvertOperation(), and SetupAndTrackLayerOutputSlot().

381 {
382 
383  VLOG(DRIVER) << "Converter::ConvertL2Pool2d()";
384 
385  LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data);
386  if (!input.IsValid())
387  {
388  return Fail("%s: Operation Could not read input 0", operationName);
389  }
390 
391  const Operand* output = GetOutputOperand(operation, 0, model);
392  if (!output)
393  {
394  return Fail("%s: Could not read output 0", __func__);
395  }
396 
397  const armnn::TensorInfo& inputInfo = input.GetTensorInfo();
398  const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
399 
401  desc.m_PoolType = poolType;
404 
405  ActivationFn activation;
406 
407  auto inputSize = operation.inputs.size();
408 
409  if (inputSize >= 10)
410  {
411  // one input, 9 parameters (padding l r t b, stridex, stridey, width, height, activation type)
412  if (!GetInputScalar(operation, 1, OperandType::INT32, desc.m_PadLeft, model, data) ||
413  !GetInputScalar(operation, 2, OperandType::INT32, desc.m_PadRight, model, data) ||
414  !GetInputScalar(operation, 3, OperandType::INT32, desc.m_PadTop, model, data) ||
415  !GetInputScalar(operation, 4, OperandType::INT32, desc.m_PadBottom, model, data) ||
416  !GetInputScalar(operation, 5, OperandType::INT32, desc.m_StrideX, model, data) ||
417  !GetInputScalar(operation, 6, OperandType::INT32, desc.m_StrideY, model, data) ||
418  !GetInputScalar(operation, 7, OperandType::INT32, desc.m_PoolWidth, model, data) ||
419  !GetInputScalar(operation, 8, OperandType::INT32, desc.m_PoolHeight, model, data) ||
420  !GetInputActivationFunction(operation, 9, activation, model, data))
421  {
422  return Fail("%s: Operation has invalid inputs", operationName);
423  }
424 
425  if (Is12OrLaterOperand(*output))
426  {
427  desc.m_DataLayout = OptionalDataLayout(operation, 10, model, data);
428  }
429  }
430  else
431  {
432  // one input, 6 parameters (padding, stridex, stridey, width, height, activation type)
433  ::android::nn::PaddingScheme scheme;
434  if (!GetInputPaddingScheme(operation, 1, scheme, model, data) ||
435  !GetInputScalar(operation, 2, OperandType::INT32, desc.m_StrideX, model, data) ||
436  !GetInputScalar(operation, 3, OperandType::INT32, desc.m_StrideY, model, data) ||
437  !GetInputScalar(operation, 4, OperandType::INT32, desc.m_PoolWidth, model, data) ||
438  !GetInputScalar(operation, 5, OperandType::INT32, desc.m_PoolHeight, model, data) ||
439  !GetInputActivationFunction(operation, 6, activation, model, data))
440  {
441  return Fail("%s: Operation has invalid inputs", operationName);
442  }
443 
444  if (Is12OrLaterOperand(*output))
445  {
446  desc.m_DataLayout = OptionalDataLayout(operation, 7, model, data);
447  }
448 
449  const armnnUtils::DataLayoutIndexed dataLayout(desc.m_DataLayout);
450  const unsigned int inputWidth = inputInfo.GetShape()[dataLayout.GetWidthIndex()];
451  const unsigned int inputHeight = inputInfo.GetShape()[dataLayout.GetHeightIndex()];
452 
453  CalcPadding(inputWidth, desc.m_PoolWidth, desc.m_StrideX, desc.m_PadLeft, desc.m_PadRight, scheme);
454  CalcPadding(inputHeight, desc.m_PoolHeight, desc.m_StrideY, desc.m_PadTop, desc.m_PadBottom, scheme);
455  }
456 
457  bool isSupported = false;
458 
459  auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported)
460  {
463  data.m_Backends,
464  isSupported,
465  inputInfo,
466  outputInfo,
467  desc);
468 
469  };
470 
471  if(IsDynamicTensor(outputInfo))
472  {
473  isSupported = AreDynamicTensorsSupported();
474  }
475  else
476  {
477  validateFunc(outputInfo, isSupported);
478  }
479 
480  if (!isSupported)
481  {
482  return false;
483  }
484 
485  armnn::IConnectableLayer* pooling2dLayer = data.m_Network->AddPooling2dLayer(desc);
486  if (!pooling2dLayer)
487  {
488  return Fail("%s: AddPooling2dLayer failed", __func__);
489  }
490 
491  input.Connect(pooling2dLayer->GetInputSlot(0));
492 
493  if (!isSupported)
494  {
495  return false;
496  }
497 
498  return SetupAndTrackLayerOutputSlot(operation, 0, *pooling2dLayer, model,
499  data, nullptr, validateFunc, activation);
500 }
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
uint32_t m_PadBottom
Padding bottom value in the height dimension.
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
uint32_t m_PadLeft
Padding left value in the width dimension.
const std::vector< armnn::BackendId > m_Backends
bool GetInputActivationFunction(const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
uint32_t m_PoolWidth
Pooling width value.
void Connect(armnn::IInputSlot &inputSlot)
uint32_t m_PadTop
Padding top value in the height dimension.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
uint32_t m_PoolHeight
Pooling height value.
bool AreDynamicTensorsSupported()
Checks for ArmNN support of dynamic tensors.
uint32_t m_PadRight
Padding right value in the width dimension.
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)
const armnn::TensorInfo & GetTensorInfo() const
armnn::DataLayout OptionalDataLayout(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data)
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout...
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
bool IsDynamicTensor(const armnn::TensorInfo &tensorInfo)
Checks if a tensor info represents a dynamic tensor.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
LayerInputHandle ConvertToLayerInputHandle(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data, const armnn::PermutationVector &dimensionMappings, const LayerInputHandle *inputHandle)
::android::nn::Operand Operand
bool SetupAndTrackLayerOutputSlot(const Operation &operation, uint32_t operationOutputIndex, armnn::IConnectableLayer &layer, uint32_t layerOutputIndex, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc, const ActivationFn &activationFunction, bool inferOutputShapes)
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
bool GetInputPaddingScheme(const Operation &operation, uint32_t inputIndex, PaddingScheme &outPaddingScheme, const Model &model, const ConversionData &data)
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
bool IsPooling2dSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const Pooling2dDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
A Pooling2dDescriptor for the Pooling2dLayer.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.

◆ ConvertReduce()

bool ConvertReduce ( const Operation operation,
const Model model,
ConversionData data,
armnn::ReduceOperation  reduceOperation 
)

Definition at line 502 of file ConversionUtils.cpp.

References AreDynamicTensorsSupported(), LayerInputHandle::Connect(), ConvertToLayerInputHandle(), FORWARD_LAYER_SUPPORT_FUNC, GetInputOperand(), GetInputScalar(), IConnectableLayer::GetInputSlot(), TensorInfo::GetNumDimensions(), GetOutputOperand(), LayerInputHandle::GetTensorInfo(), GetTensorInfoForOperand(), GetTensorInt32Values(), IsDynamicTensor(), armnn::IsReduceSupported(), LayerInputHandle::IsValid(), ConversionData::m_Backends, ReduceDescriptor::m_KeepDims, ConversionData::m_Network, ReduceDescriptor::m_ReduceOperation, ReduceDescriptor::m_vAxis, and SetupAndTrackLayerOutputSlot().

Referenced by Converter::ConvertOperation(), and SetupAndTrackLayerOutputSlot().

506 {
507  armnn::ReduceDescriptor descriptor;
508  descriptor.m_ReduceOperation = reduceOperation;
509 
510  LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data);
511  if (!input.IsValid())
512  {
513  return Fail("%s: Operation has invalid inputs", __func__);
514  }
515  const armnn::TensorInfo& inputInfo = input.GetTensorInfo();
516 
517  const Operand* output = GetOutputOperand(operation, 0, model);
518  if (!output)
519  {
520  return Fail("%s: Could not read output 0", __func__);
521  }
522  const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
523 
524  const Operand* axisOperand = GetInputOperand(operation, 1, model);
525  if (!axisOperand)
526  {
527  return Fail("%s: Could not read input 1", __func__);
528  }
529  std::vector<int32_t> axis;
530  if (!GetTensorInt32Values(*axisOperand, axis, model, data))
531  {
532  return Fail("%s: Input 1 has invalid values", __func__);
533  }
534 
535  // Convert the axis to unsigned int and remove duplicates.
536  unsigned int rank = inputInfo.GetNumDimensions();
537  std::set<unsigned int> uniqueAxis;
538  std::transform(axis.begin(), axis.end(),
539  std::inserter(uniqueAxis, uniqueAxis.begin()),
540  [rank](int i) -> unsigned int { return (i + rank) % rank; });
541  descriptor.m_vAxis.assign(uniqueAxis.begin(), uniqueAxis.end());
542 
543  // Get the "keep dims" flag.
544  if (!GetInputScalar(operation, 2, OperandType::BOOL, descriptor.m_KeepDims, model, data))
545  {
546  return Fail("%s: Could not read input 2", __func__);
547  }
548 
549  bool isSupported = false;
550  auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported)
551  {
554  data.m_Backends,
555  isSupported,
556  inputInfo,
557  outputInfo,
558  descriptor);
559  };
560 
561  if(!IsDynamicTensor(outputInfo))
562  {
563  validateFunc(outputInfo, isSupported);
564  }
565  else
566  {
567  isSupported = AreDynamicTensorsSupported();
568  }
569 
570  if (!isSupported)
571  {
572  return false;
573  }
574 
575  armnn::IConnectableLayer* const layer = data.m_Network->AddReduceLayer(descriptor);
576  assert(layer != nullptr);
577  input.Connect(layer->GetInputSlot(0));
578 
579  return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data, nullptr, validateFunc);
580 }
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
const std::vector< armnn::BackendId > m_Backends
bool m_KeepDims
if true then output shape has no change.
void Connect(armnn::IInputSlot &inputSlot)
ReduceOperation m_ReduceOperation
Specifies the reduction operation to execute.
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
bool AreDynamicTensorsSupported()
Checks for ArmNN support of dynamic tensors.
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)
const armnn::TensorInfo & GetTensorInfo() const
A ReduceDescriptor for the REDUCE operators.
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
bool GetTensorInt32Values(const Operand &operand, std::vector< int32_t > &outValues, const Model &model, const ConversionData &data)
bool IsDynamicTensor(const armnn::TensorInfo &tensorInfo)
Checks if a tensor info represents a dynamic tensor.
std::vector< uint32_t > m_vAxis
The indices of the dimensions to reduce.
LayerInputHandle ConvertToLayerInputHandle(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data, const armnn::PermutationVector &dimensionMappings, const LayerInputHandle *inputHandle)
::android::nn::Operand Operand
bool SetupAndTrackLayerOutputSlot(const Operation &operation, uint32_t operationOutputIndex, armnn::IConnectableLayer &layer, uint32_t layerOutputIndex, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc, const ActivationFn &activationFunction, bool inferOutputShapes)
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
bool IsReduceSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const ReduceDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195

◆ ConvertToActivation()

bool ConvertToActivation ( const Operation operation,
const char *  operationName,
const armnn::ActivationDescriptor activationDesc,
const Model model,
ConversionData data 
)

Definition at line 583 of file ConversionUtils.cpp.

References AreDynamicTensorsSupported(), ARMNN_ASSERT, LayerInputHandle::Connect(), ConvertToLayerInputHandle(), FORWARD_LAYER_SUPPORT_FUNC, IConnectableLayer::GetInputSlot(), GetOutputOperand(), LayerInputHandle::GetTensorInfo(), GetTensorInfoForOperand(), armnn::IsActivationSupported(), IsDynamicTensor(), LayerInputHandle::IsValid(), ConversionData::m_Backends, ConversionData::m_Network, and SetupAndTrackLayerOutputSlot().

Referenced by Converter::ConvertOperation(), and SetupAndTrackLayerOutputSlot().

588 {
589  LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data);
590  if (!input.IsValid())
591  {
592  return Fail("%s: Input 0 is invalid", operationName);
593  }
594 
595  const Operand* outputOperand = GetOutputOperand(operation, 0, model);
596  if (!outputOperand)
597  {
598  return false;
599  }
600 
601  const armnn::TensorInfo& outInfo = GetTensorInfoForOperand(*outputOperand);
602 
603  bool isSupported = false;
604 
605  auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
606  {
609  data.m_Backends,
610  isSupported,
611  input.GetTensorInfo(),
612  outInfo,
613  activationDesc);
614  };
615 
616  if(IsDynamicTensor(outInfo))
617  {
618  isSupported = AreDynamicTensorsSupported();
619  }
620  else
621  {
622  validateFunc(outInfo, isSupported);
623  }
624 
625  if (!isSupported)
626  {
627  return false;
628  }
629 
630  armnn::IConnectableLayer* layer = data.m_Network->AddActivationLayer(activationDesc);
631  ARMNN_ASSERT(layer != nullptr);
632  input.Connect(layer->GetInputSlot(0));
633 
634  return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data, nullptr, validateFunc);
635 }
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
const std::vector< armnn::BackendId > m_Backends
void Connect(armnn::IInputSlot &inputSlot)
bool AreDynamicTensorsSupported()
Checks for ArmNN support of dynamic tensors.
const armnn::TensorInfo & GetTensorInfo() const
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
bool IsDynamicTensor(const armnn::TensorInfo &tensorInfo)
Checks if a tensor info represents a dynamic tensor.
LayerInputHandle ConvertToLayerInputHandle(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data, const armnn::PermutationVector &dimensionMappings, const LayerInputHandle *inputHandle)
::android::nn::Operand Operand
bool SetupAndTrackLayerOutputSlot(const Operation &operation, uint32_t operationOutputIndex, armnn::IConnectableLayer &layer, uint32_t layerOutputIndex, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc, const ActivationFn &activationFunction, bool inferOutputShapes)
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
bool IsActivationSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const ActivationDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.

◆ ConvertToLayerInputHandle()

LayerInputHandle ConvertToLayerInputHandle ( const Operation operation,
uint32_t  inputIndex,
const Model model,
ConversionData data,
const armnn::PermutationVector dimensionMappings,
const LayerInputHandle inputHandle 
)

Definition at line 204 of file ConversionUtils.cpp.

References ConvertOperandToConstTensorPin(), FORWARD_LAYER_SUPPORT_FUNC, ConstTensorPin::GetConstTensor(), TensorInfo::GetDataType(), BaseTensor< MemoryType >::GetInfo(), GetInputOperand(), IConnectableLayer::GetOutputSlot(), GetTensorInfoForOperand(), armnn::IsConstantSupported(), IsDynamicTensor(), armnn::IsInputSupported(), ConstTensorPin::IsValid(), ConversionData::m_Backends, ConversionData::m_DynamicInputsEncountered, ConversionData::m_Network, ConversionData::m_OutputSlotForOperand, UnsupportedOperand< OperandType >::m_type, and IOutputSlot::SetTensorInfo().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), and GetOptionalBool().

210 {
211 
212  const Operand* operand = GetInputOperand(operation, inputIndex, model);
213  if (!operand)
214  {
215  Fail("%s: failed to get input operand %i", __func__, inputIndex);
216  return LayerInputHandle();
217  }
218 
219  if (!IsOperandTypeSupportedForTensors(operand->type))
220  {
221  VLOG(DRIVER) << __func__ << ": unsupported operand type for tensor: " << operand->type;
222  return LayerInputHandle();
223  }
224 
225  try
226  {
227  armnn::TensorInfo operandTensorInfo = GetTensorInfoForOperand(*operand);
228 
229  if (IsDynamicTensor(operandTensorInfo))
230  {
231  data.m_DynamicInputsEncountered = true;
232 
233  const uint32_t operandIndex = operation.inputs[inputIndex];
234 
235  // Check if the dynamic input tensors have been inferred by one of the previous layers
236  // If not we can't support them
237  if (data.m_OutputSlotForOperand.size() >= operandIndex && data.m_OutputSlotForOperand[operandIndex])
238  {
239  operandTensorInfo = data.m_OutputSlotForOperand[operandIndex]->GetTensorInfo();
240  }
241  else
242  {
243  Fail("%s: Type 2 dynamic input tensors are not supported", __func__);
244  return LayerInputHandle();
245  }
246  }
247 
248  switch (operand->lifetime)
249  {
250  case OperandLifeTime::SUBGRAPH_INPUT:
251  {
252  // NOTE: We must check whether we can support the input tensor on at least one
253  // of the provided backends; otherwise we cannot convert the operation
254  bool isInputSupported = false;
257  data.m_Backends,
258  isInputSupported,
259  operandTensorInfo);
260 
261  if (!isInputSupported)
262  {
263  Fail("%s: unsupported input tensor", __func__);
264  return LayerInputHandle();
265  }
266 
267  [[clang::fallthrough]]; // intentional fallthrough
268  }
269  case OperandLifeTime::TEMPORARY_VARIABLE: // intentional fallthrough
270  case OperandLifeTime::SUBGRAPH_OUTPUT:
271  {
272  // The tensor is either an operand internal to the model, or a model input.
273  // It can be associated with an ArmNN output slot for an existing layer.
274 
275  // m_OutputSlotForOperand[...] can be nullptr if the previous layer could not be converted
276  const uint32_t operandIndex = operation.inputs[inputIndex];
277  return LayerInputHandle(true, data.m_OutputSlotForOperand[operandIndex], operandTensorInfo);
278  }
279  case OperandLifeTime::CONSTANT_COPY: // intentional fallthrough
280  case OperandLifeTime::POINTER:
281  case OperandLifeTime::CONSTANT_REFERENCE:
282  {
283  auto constantTensorDataType = operandTensorInfo.GetDataType();
284  // The tensor has an already known constant value, and can be converted into an ArmNN Constant layer.
285  ConstTensorPin tensorPin = ConvertOperandToConstTensorPin(*operand,
286  model,
287  data,
288  dimensionMappings,
289  nullptr,
290  false,
291  &constantTensorDataType);
292  if (tensorPin.IsValid())
293  {
294  bool isSupported = false;
297  data.m_Backends,
298  isSupported,
299  tensorPin.GetConstTensor().GetInfo());
300  if (!isSupported)
301  {
302  return LayerInputHandle();
303  }
304 
305  armnn::IConnectableLayer* constantLayer =
306  data.m_Network->AddConstantLayer(tensorPin.GetConstTensor());
307  armnn::IOutputSlot& outputSlot = constantLayer->GetOutputSlot(0);
308  armnn::TensorInfo constantTensorInfo = tensorPin.GetConstTensor().GetInfo();
309  outputSlot.SetTensorInfo(constantTensorInfo);
310 
311  return LayerInputHandle(true, &outputSlot, constantTensorInfo);
312  }
313  else
314  {
315  Fail("%s: invalid operand tensor", __func__);
316  return LayerInputHandle();
317  }
318  break;
319  }
320  default:
321  {
322  VLOG(DRIVER) << __func__ << ": unsupported lifetime for input tensor: " << operand->lifetime;
323  return LayerInputHandle();
324  }
325  }
326  }
328  {
329  VLOG(DRIVER) << __func__ << ": Operand type: " << e.m_type << " not supported in ArmnnDriver";
330  return LayerInputHandle();
331  }
332 }
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
std::vector< armnn::IOutputSlot * > m_OutputSlotForOperand
const std::vector< armnn::BackendId > m_Backends
ConstTensorPin ConvertOperandToConstTensorPin(const Operand &operand, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings, const armnn::TensorShape *overrideTensorShape, bool optional, const armnn::DataType *overrideDataType)
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
An output connection slot for a layer.
Definition: INetwork.hpp:41
DataType GetDataType() const
Definition: Tensor.hpp:198
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
const TensorInfo & GetInfo() const
Definition: Tensor.hpp:295
bool IsDynamicTensor(const armnn::TensorInfo &tensorInfo)
Checks if a tensor info represents a dynamic tensor.
bool IsInputSupported(const BackendId &backend, const TensorInfo &input, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
::android::nn::Operand Operand
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
const armnn::ConstTensor & GetConstTensor() const
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
bool IsConstantSupported(const BackendId &backend, const TensorInfo &output, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.

◆ DequantizeAndMakeConstTensorPin()

ConstTensorPin DequantizeAndMakeConstTensorPin ( const Operation operation,
const Model model,
const ConversionData data,
size_t  operandIndex,
bool  optional 
)

Definition at line 720 of file ConversionUtils.cpp.

References ConstTensorPin::ConstTensorPin(), ConvertOperationInputToConstTensorPin(), DequantizeIfRequired(), g_DontPermute, INVALID_OPERAND, NOT_REQUIRED, and SUCCESS.

Referenced by Converter::ConvertOperation().

725 {
726  DequantizeResult dequantized = DequantizeIfRequired(operandIndex,operation, model, data);
727 
728  DequantizeStatus status = std::get<3>(dequantized);
729  switch (status)
730  {
731  case DequantizeStatus::INVALID_OPERAND:
732  {
733  // return invalid const tensor pin
734  return ConstTensorPin();
735  }
736  case DequantizeStatus::NOT_REQUIRED:
737  {
739  operation, operandIndex, model, data, g_DontPermute, nullptr, optional);
740  }
741  case DequantizeStatus::SUCCESS:
742  default:
743  {
744  return ConstTensorPin(
745  std::get<2>(dequantized), std::get<0>(dequantized).get(), std::get<1>(dequantized), g_DontPermute);
746  }
747  }
748 }
const armnn::PermutationVector g_DontPermute
ConstTensorPin ConvertOperationInputToConstTensorPin(const Operation &operation, uint32_t inputIndex, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings=g_DontPermute, const armnn::TensorShape *overrideTensorShape=nullptr, bool optional=false)
std::tuple< std::unique_ptr< float[]>, size_t, armnn::TensorInfo, DequantizeStatus > DequantizeResult
DequantizeResult DequantizeIfRequired(size_t operand_index, const Operation &operation, const Model &model, const ConversionData &data)

◆ DequantizeIfRequired()

DequantizeResult DequantizeIfRequired ( size_t  operand_index,
const Operation operation,
const Model model,
const ConversionData data 
)

Definition at line 637 of file ConversionUtils.cpp.

References ARMNN_ASSERT, armnn::Float32, GetInputOperand(), getMainModel(), GetOperandValueReadOnlyAddress(), INVALID_OPERAND, IsOperandConstant(), IsQSymm8(), NOT_REQUIRED, and SUCCESS.

Referenced by DequantizeAndMakeConstTensorPin().

641 {
642  const Operand* weightsOperand = GetInputOperand(operation, operand_index, model);
643  if (!weightsOperand)
644  {
645  return { nullptr, 0, armnn::TensorInfo(), DequantizeStatus::INVALID_OPERAND };
646  }
647 
648  if (IsOperandConstant(*weightsOperand))
649  {
650  // Weights are already constant
651  return { nullptr, 0, armnn::TensorInfo(), DequantizeStatus::NOT_REQUIRED };
652  }
653 
654  const size_t weightsInputIndex = operation.inputs[operand_index];
655 
656  // The weights are a non const tensor, this indicates they might be the output of a dequantize op.
657  // Iterate over the nodes and find the previous operation which should be DEQUANTIZE
658  for (uint32_t operationIdx = 0; operationIdx < getMainModel(model).operations.size(); ++operationIdx)
659  {
660  // Search for the DEQUANTIZE op which has the operand with index equal to operandIndex
661  const auto& operationIt = getMainModel(model).operations[operationIdx];
662  if (operationIt.type != OperationType::DEQUANTIZE)
663  {
664  continue;
665  }
666 
667  size_t outOpIndex = weightsInputIndex + 1;
668  for (size_t i = 0; outOpIndex != weightsInputIndex && i < operationIt.outputs.size(); ++i)
669  {
670  outOpIndex = operationIt.outputs[i];
671  }
672 
673  if (outOpIndex != weightsInputIndex)
674  {
675  continue;
676  }
677 
678  const Operand* operand = GetInputOperand(operationIt, 0, model);
679  ARMNN_ASSERT(operand);
680 
681  if (!IsQSymm8(*operand))
682  {
683  // Only supporting dequantize from QSYMM8 to FLOAT
684  break;
685  }
686 
687  // Allocate a new buffer for the dequantized data and manually dequantize
688  const void* startValue = GetOperandValueReadOnlyAddress(*operand, model, data);
689  if (!startValue)
690  {
691  // Failed to get the operand address
692  break;
693  }
694 
695  const uint8_t* quantizedBuffer = reinterpret_cast<const uint8_t*>(startValue);
696  size_t dequantizedBufferLength = operand->location.length;
697  const float quantizationScale = operand->scale;
698 
699  auto dequantizedBuffer = std::make_unique<float[]>(dequantizedBufferLength + 1);
700  for (size_t i = 0; i < dequantizedBufferLength; ++i)
701  {
702  float* dstPtr = dequantizedBuffer.get();
703  ARMNN_ASSERT(dstPtr);
704  *dstPtr++ = quantizedBuffer[i] * quantizationScale;
705  }
706 
707  // Construct tensor info for dequantized ConstTensor
708  armnn::TensorInfo tensorInfo(operand->dimensions.size(),
709  operand->dimensions.data(),
711 
712  return { std::move(dequantizedBuffer), dequantizedBufferLength * sizeof(float),
713  std::move(tensorInfo),
714  DequantizeStatus::SUCCESS };
715  }
716 
717  return { nullptr, 0, armnn::TensorInfo() , DequantizeStatus::NOT_REQUIRED};
718 }
bool IsQSymm8(const Operand &operand)
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
::android::nn::Operand Operand
const android::nn::Model::Subgraph & getMainModel(const android::nn::Model &model)
bool IsOperandConstant(const Operand &operand)

◆ DumpJsonProfilingIfRequired()

void DumpJsonProfilingIfRequired ( bool  gpuProfilingEnabled,
const std::string &  dumpDir,
armnn::NetworkId  networkId,
const armnn::IProfiler profiler 
)

Definition at line 350 of file CanonicalUtils.cpp.

References ARMNN_ASSERT, and IProfiler::Print().

Referenced by ArmnnPreparedModel::~ArmnnPreparedModel().

354 {
355  // Check if profiling is required.
356  if (!gpuProfilingEnabled)
357  {
358  return;
359  }
360 
361  // The dump directory must exist in advance.
362  if (dumpDir.empty())
363  {
364  return;
365  }
366 
367  ARMNN_ASSERT(profiler);
368 
369  // Set the name of the output profiling file.
370  fs::path dumpPath = dumpDir;
371  const fs::path fileName = dumpPath / (std::to_string(networkId) + "_profiling.json");
372 
373  // Open the ouput file for writing.
374  std::ofstream fileStream;
375  fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
376 
377  if (!fileStream.good())
378  {
379  VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
380  return;
381  }
382 
383  // Write the profiling info to a JSON file.
384  profiler->Print(fileStream);
385 }
void Print(std::ostream &outStream) const
Print stats for events in JSON Format to the given output stream.
Definition: Profiling.cpp:630
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14

◆ DumpTensor()

void DumpTensor ( const std::string &  dumpDir,
const std::string &  requestName,
const std::string &  tensorName,
const TensorType &  tensor 
)

Definition at line 217 of file CanonicalUtils.cpp.

References TensorShape::AreAllDimensionsSpecified(), armnn::Boolean, armnn::Float16, armnn::Float32, TensorShape::GetNumElements(), armnn::QAsymmS8, armnn::QAsymmU8, and armnn::Signed32.

Referenced by ArmnnPreparedModel::getUnderlyingResource().

221 {
222  // The dump directory must exist in advance.
223  fs::path dumpPath = dumpDir;
224  const fs::path fileName = dumpPath / (requestName + "_" + tensorName + ".dump");
225 
226  std::ofstream fileStream;
227  fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
228 
229  if (!fileStream.good())
230  {
231  VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
232  return;
233  }
234 
235  DumpElementFunction<TensorType> dumpElementFunction = nullptr;
236 
237  switch (tensor.GetDataType())
238  {
240  {
241  dumpElementFunction = &DumpTensorElement<TensorType, float>;
242  break;
243  }
245  {
246  dumpElementFunction = &DumpTensorElement<TensorType, uint8_t, uint32_t>;
247  break;
248  }
250  {
251  dumpElementFunction = &DumpTensorElement<TensorType, int32_t>;
252  break;
253  }
255  {
256  dumpElementFunction = &DumpTensorElement<TensorType, armnn::Half>;
257  break;
258  }
260  {
261  dumpElementFunction = &DumpTensorElement<TensorType, int8_t, int32_t>;
262  break;
263  }
265  {
266  dumpElementFunction = &DumpTensorElement<TensorType, bool>;
267  break;
268  }
269  default:
270  {
271  dumpElementFunction = nullptr;
272  }
273  }
274 
275  if (dumpElementFunction != nullptr)
276  {
277  const unsigned int numDimensions = tensor.GetNumDimensions();
278  const armnn::TensorShape shape = tensor.GetShape();
279 
280  if (!shape.AreAllDimensionsSpecified())
281  {
282  fileStream << "Cannot dump tensor elements: not all dimensions are specified" << std::endl;
283  return;
284  }
285  fileStream << "# Number of elements " << tensor.GetNumElements() << std::endl;
286 
287  if (numDimensions == 0)
288  {
289  fileStream << "# Shape []" << std::endl;
290  return;
291  }
292  fileStream << "# Shape [" << shape[0];
293  for (unsigned int d = 1; d < numDimensions; ++d)
294  {
295  fileStream << "," << shape[d];
296  }
297  fileStream << "]" << std::endl;
298  fileStream << "Each line contains the data of each of the elements of dimension0. In NCHW and NHWC, each line"
299  " will be a batch" << std::endl << std::endl;
300 
301  // Split will create a new line after all elements of the first dimension
302  // (in a 4, 3, 2, 3 tensor, there will be 4 lines of 18 elements)
303  unsigned int split = 1;
304  if (numDimensions == 1)
305  {
306  split = shape[0];
307  }
308  else
309  {
310  for (unsigned int i = 1; i < numDimensions; ++i)
311  {
312  split *= shape[i];
313  }
314  }
315 
316  // Print all elements in the tensor
317  for (unsigned int elementIndex = 0; elementIndex < tensor.GetNumElements(); ++elementIndex)
318  {
319  (*dumpElementFunction)(tensor, elementIndex, fileStream);
320 
321  if ( (elementIndex + 1) % split == 0 )
322  {
323  fileStream << std::endl;
324  }
325  }
326  fileStream << std::endl;
327  }
328  else
329  {
330  fileStream << "Cannot dump tensor elements: Unsupported data type "
331  << static_cast<unsigned int>(tensor.GetDataType()) << std::endl;
332  }
333 
334  if (!fileStream.good())
335  {
336  VLOG(DRIVER) << "An error occurred when writing to file %s" << fileName.c_str();
337  }
338 }
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified...
Definition: Tensor.cpp:181
bool AreAllDimensionsSpecified() const
Checks if there is at least one dimension not specified.
Definition: Tensor.cpp:241

◆ DumpTensor< armnn::ConstTensor >()

template void armnn_driver::DumpTensor< armnn::ConstTensor > ( const std::string &  dumpDir,
const std::string &  requestName,
const std::string &  tensorName,
const armnn::ConstTensor tensor 
)

◆ DumpTensor< armnn::Tensor >()

template void armnn_driver::DumpTensor< armnn::Tensor > ( const std::string &  dumpDir,
const std::string &  requestName,
const std::string &  tensorName,
const armnn::Tensor tensor 
)

◆ ExportNetworkGraphToDotFile()

std::string ExportNetworkGraphToDotFile ( const armnn::IOptimizedNetwork optimizedNetwork,
const std::string &  dumpDir 
)

Definition at line 387 of file CanonicalUtils.cpp.

References GetFileTimestamp(), IOptimizedNetwork::SerializeToDot(), and armnn::Success.

Referenced by ArmnnDriverImpl::PrepareArmnnModel(), and ArmnnDriverImpl::PrepareArmnnModelFromCache().

389 {
390  std::string fileName;
391  // The dump directory must exist in advance.
392  if (dumpDir.empty())
393  {
394  return fileName;
395  }
396 
397  std::string timestamp = GetFileTimestamp();
398  if (timestamp.empty())
399  {
400  return fileName;
401  }
402 
403  // Set the name of the output .dot file.
404  fs::path dumpPath = dumpDir;
405  fs::path tempFilePath = dumpPath / (timestamp + "_networkgraph.dot");
406  fileName = tempFilePath.string();
407 
408  VLOG(DRIVER) << "Exporting the optimized network graph to file: %s" << fileName.c_str();
409 
410  // Write the network graph to a dot file.
411  std::ofstream fileStream;
412  fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc);
413 
414  if (!fileStream.good())
415  {
416  VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
417  return fileName;
418  }
419 
420  if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success)
421  {
422  VLOG(DRIVER) << "An error occurred when writing to file %s" << fileName.c_str();
423  }
424  return fileName;
425 }
Status SerializeToDot(std::ostream &stream) const
Definition: Network.cpp:485
std::string GetFileTimestamp()

◆ GetFileTimestamp()

std::string GetFileTimestamp ( )

Definition at line 555 of file CanonicalUtils.cpp.

Referenced by ExportNetworkGraphToDotFile(), and SerializeNetwork().

556 {
557  // used to get a timestamp to name diagnostic files (the ArmNN serialized graph
558  // and getSupportedOperations.txt files)
559  timespec ts;
560  int iRet = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
561  std::stringstream ss;
562  if (iRet == 0)
563  {
564  ss << std::to_string(ts.tv_sec) << "_" << std::to_string(ts.tv_nsec);
565  }
566  else
567  {
568  VLOG(DRIVER) << "clock_gettime failed with errno " <<
569  std::to_string(errno).c_str() << " : " <<
570  std::strerror(errno);
571  }
572  return ss.str();
573 }

◆ GetInputActivationFunction()

bool armnn_driver::GetInputActivationFunction ( const Operation operation,
uint32_t  inputIndex,
ActivationFn &  outActivationFunction,
const Model model,
const ConversionData data 
)
inline

Definition at line 813 of file ConversionUtils.hpp.

References GetInputActivationFunctionImpl().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), and GetOptionalInputActivation().

818 {
819  return GetInputActivationFunctionImpl(operation,
820  inputIndex,
821  OperandType::INT32,
822  outActivationFunction,
823  model,
824  data);
825 }
bool GetInputActivationFunctionImpl(const Operation &operation, uint32_t inputIndex, OperandType type, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)

◆ GetInputActivationFunctionFromTensor()

bool armnn_driver::GetInputActivationFunctionFromTensor ( const Operation operation,
uint32_t  inputIndex,
ActivationFn &  outActivationFunction,
const Model model,
const ConversionData data 
)
inline

Definition at line 827 of file ConversionUtils.hpp.

References GetInputActivationFunctionImpl().

Referenced by Converter::ConvertOperation().

832 {
833  // This only accepts a 1-D tensor of size 1
834  return GetInputActivationFunctionImpl(operation,
835  inputIndex,
836  OperandType::INT32,
837  outActivationFunction,
838  model,
839  data);
840 }
bool GetInputActivationFunctionImpl(const Operation &operation, uint32_t inputIndex, OperandType type, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)

◆ GetInputActivationFunctionImpl()

bool armnn_driver::GetInputActivationFunctionImpl ( const Operation operation,
uint32_t  inputIndex,
OperandType  type,
ActivationFn &  outActivationFunction,
const Model model,
const ConversionData data 
)
inline

Definition at line 790 of file ConversionUtils.hpp.

References GetInputScalar().

Referenced by GetInputActivationFunction(), and GetInputActivationFunctionFromTensor().

796 {
797  if (type != OperandType::INT32 && type != OperandType::TENSOR_INT32)
798  {
799  VLOG(DRIVER) << __func__ << ": unexpected operand type: " << type
800  << " should be OperandType::INT32 or OperandType::TENSOR_INT32";
801  return false;
802  }
803 
804  int32_t activationFunctionAsInt;
805  if (!GetInputScalar(operation, inputIndex, type, activationFunctionAsInt, model, data))
806  {
807  return Fail("%s: failed to get activation input value", __func__);
808  }
809  outActivationFunction = static_cast<ActivationFn>(activationFunctionAsInt);
810  return true;
811 }
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)

◆ GetInputFloat32()

bool armnn_driver::GetInputFloat32 ( const Operation operation,
uint32_t  inputIndex,
float &  outValue,
const Model model,
const ConversionData data 
)
inline

Definition at line 781 of file ConversionUtils.hpp.

References GetInputScalar().

Referenced by Converter::ConvertOperation().

786 {
787  return GetInputScalar(operation, inputIndex, OperandType::FLOAT32, outValue, model, data);
788 }
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)

◆ GetInputInt32()

bool armnn_driver::GetInputInt32 ( const Operation operation,
uint32_t  inputIndex,
int32_t &  outValue,
const Model model,
const ConversionData data 
)
inline

Definition at line 772 of file ConversionUtils.hpp.

References GetInputScalar().

Referenced by Converter::ConvertOperation(), and GetInputPaddingScheme().

777 {
778  return GetInputScalar(operation, inputIndex, OperandType::INT32, outValue, model, data);
779 }
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)

◆ GetInputOperand()

const Operand* armnn_driver::GetInputOperand ( const Operation operation,
uint32_t  inputIndex,
const Model model,
bool  failOnIndexOutOfBounds = true 
)
inline

Definition at line 633 of file ConversionUtils.hpp.

References ARMNN_ASSERT, and getMainModel().

Referenced by Converter::ConvertOperation(), ConvertOperationInputToConstTensorPin(), ConvertPaddings(), ConvertReduce(), ConvertToLayerInputHandle(), DequantizeIfRequired(), GetInputScalar(), GetOperandType(), GetOptionalBool(), IsWeightsValid(), and OptionalDataLayout().

637 {
638  if (inputIndex >= operation.inputs.size())
639  {
640  if (failOnIndexOutOfBounds)
641  {
642  Fail("%s: invalid input index: %i out of %i", __func__, inputIndex, operation.inputs.size());
643  }
644  return nullptr;
645  }
646 
647  // Model should have been validated beforehand
648  ARMNN_ASSERT(operation.inputs[inputIndex] < getMainModel(model).operands.size());
649  return &getMainModel(model).operands[operation.inputs[inputIndex]];
650 }
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
const android::nn::Model::Subgraph & getMainModel(const android::nn::Model &model)

◆ GetInputPaddingScheme()

bool GetInputPaddingScheme ( const Operation operation,
uint32_t  inputIndex,
PaddingScheme &  outPaddingScheme,
const Model model,
const ConversionData data 
)

Definition at line 750 of file ConversionUtils.cpp.

References GetInputInt32().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), and GetOptionalBool().

755 {
756  int32_t paddingSchemeAsInt;
757  if (!GetInputInt32(operation, inputIndex, paddingSchemeAsInt, model, data))
758  {
759  return Fail("%s: failed to get padding scheme input value", __func__);
760  }
761 
762  outPaddingScheme = static_cast<::android::nn::PaddingScheme>(paddingSchemeAsInt);
763  return true;
764 }
bool GetInputInt32(const Operation &operation, uint32_t inputIndex, int32_t &outValue, const Model &model, const ConversionData &data)

◆ GetInputScalar()

bool armnn_driver::GetInputScalar ( const Operation operation,
uint32_t  inputIndex,
OperandType  type,
OutputType &  outValue,
const Model model,
const ConversionData data,
bool  optional = false 
)

Definition at line 732 of file ConversionUtils.hpp.

References GetInputOperand(), and GetOperandValueReadOnlyAddress().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), GetInputActivationFunctionImpl(), GetInputFloat32(), GetInputInt32(), and GetOptionalConvolutionDilationParams().

739 {
740  const Operand* operand = GetInputOperand(operation, inputIndex, model);
741  if (!optional && !operand)
742  {
743  return Fail("%s: invalid input operand at index %i", __func__, inputIndex);
744  }
745 
746  if (!optional && operand->type != type)
747  {
748  VLOG(DRIVER) << __func__ << ": unexpected operand type: " << operand->type << " should be: " << type;
749  return false;
750  }
751 
752  if (!optional && operand->location.length != sizeof(OutputType))
753  {
754  return Fail("%s: incorrect operand location length: %i (should be %i)",
755  __func__, operand->location.length, sizeof(OutputType));
756  }
757 
758  const void* valueAddress = GetOperandValueReadOnlyAddress(*operand, model, data);
759  if (!optional && !valueAddress)
760  {
761  return Fail("%s: failed to get address for operand", __func__);
762  }
763 
764  if(!optional)
765  {
766  outValue = *(static_cast<const OutputType*>(valueAddress));
767  }
768 
769  return true;
770 }
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
::android::nn::Operand Operand

◆ GetMemoryFromPointer()

void * GetMemoryFromPointer ( const Request::Argument &  requestArg)

Definition at line 77 of file CanonicalUtils.cpp.

78 {
79  // get the pointer memory
80  auto ptrMemory = std::visit([](std::variant<const void*, void*>&& memory)
81  {
82  if (std::holds_alternative<const void*>(memory))
83  {
84  auto ptr = std::get<const void*>(memory);
85  auto ptrMemory = static_cast<const uint8_t*>(ptr);
86  return const_cast<uint8_t*>(ptrMemory);
87  }
88  else
89  {
90  auto ptr = std::get<void*>(memory);
91  return static_cast<uint8_t*>(ptr);
92  }
93  }, requestArg.location.pointer);
94  return ptrMemory;
95 }

◆ GetMemoryFromPool()

void * GetMemoryFromPool ( DataLocation  location,
const std::vector< android::nn::RunTimePoolInfo > &  memPools 
)

Returns a pointer to a specific location in a pool`.

Definition at line 66 of file CanonicalUtils.cpp.

Referenced by GetOperandValueReadOnlyAddress().

67 {
68  // find the location within the pool
69  assert(location.poolIndex < memPools.size());
70 
71  const android::nn::RunTimePoolInfo& memPool = memPools[location.poolIndex];
72  uint8_t* memPoolBuffer = memPool.getBuffer();
73  uint8_t* memory = memPoolBuffer + location.offset;
74  return memory;
75 }

◆ GetModelSummary()

std::string GetModelSummary ( const Model model)

Definition at line 521 of file CanonicalUtils.cpp.

References GetOperandSummary().

Referenced by ArmnnPreparedModel::execute(), and ArmnnPreparedModel::executeFenced().

522 {
523  std::stringstream result;
524 
525  result << model.main.inputIndexes.size() << " input(s), "
526  << model.main.operations.size() << " operation(s), "
527  << model.main.outputIndexes.size() << " output(s), "
528  << model.main.operands.size() << " operand(s) "
529  << std::endl;
530 
531  result << "Inputs: ";
532  for (uint32_t i = 0; i < model.main.inputIndexes.size(); i++)
533  {
534  result << GetOperandSummary(model.main.operands[model.main.inputIndexes[i]]) << ", ";
535  }
536  result << std::endl;
537 
538  result << "Operations: ";
539  for (uint32_t i = 0; i < model.main.operations.size(); i++)
540  {
541  result << model.main.operations[i].type << ", ";
542  }
543  result << std::endl;
544 
545  result << "Outputs: ";
546  for (uint32_t i = 0; i < model.main.outputIndexes.size(); i++)
547  {
548  result << GetOperandSummary(model.main.operands[model.main.outputIndexes[i]]) << ", ";
549  }
550  result << std::endl;
551 
552  return result.str();
553 }
std::string GetOperandSummary(const Operand &operand)

◆ GetOperandSummary()

std::string GetOperandSummary ( const Operand operand)

Definition at line 189 of file CanonicalUtils.cpp.

Referenced by GetModelSummary().

190 {
191  std::stringstream ss;
192  ss << "operand dimensions: [ ";
193  for (unsigned int i = 0; i < operand.dimensions.size(); ++i)
194  {
195  ss << operand.dimensions[i] << " ";
196  }
197  ss << "] operand type: " << operand.type;
198  return ss.str();
199 }

◆ GetOperandType()

bool armnn_driver::GetOperandType ( const Operation operation,
uint32_t  inputIndex,
const Model model,
OperandType type 
)
inline

Definition at line 673 of file ConversionUtils.hpp.

References GetInputOperand().

Referenced by Converter::ConvertOperation().

677 {
678  const Operand* operand = GetInputOperand(operation, inputIndex, model);
679  if (!operand)
680  {
681  return Fail("%s: invalid input operand at index %i", __func__, inputIndex);
682  }
683 
684  type = operand->type;
685  return true;
686 }
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
::android::nn::Operand Operand

◆ GetOperandValueReadOnlyAddress()

const void * GetOperandValueReadOnlyAddress ( const Operand operand,
const Model model,
const ConversionData data,
bool  optional 
)

Definition at line 766 of file ConversionUtils.cpp.

References GetMemoryFromPool(), and ConversionData::m_MemPools.

Referenced by ConvertOperandToConstTensorPin(), DequantizeIfRequired(), GetInputScalar(), GetOptionalBool(), GetOutputOperand(), GetTensorInt32Values(), and OptionalDataLayout().

770 {
771  const void* valueStart = nullptr;
772  switch (operand.lifetime)
773  {
774  case OperandLifeTime::CONSTANT_COPY:
775  {
776  valueStart = model.operandValues.data() + operand.location.offset;
777  break;
778  }
779  case OperandLifeTime::POINTER:
780  {
781  // Pointer specified in the model
782  valueStart = std::get<const void*>(operand.location.pointer);
783  break;
784  }
785  case OperandLifeTime::CONSTANT_REFERENCE:
786  {
787  // Constant specified via a Memory object
788  valueStart = GetMemoryFromPool(operand.location, data.m_MemPools);
789  break;
790  }
791  case OperandLifeTime::NO_VALUE:
792  {
793  // An optional input tensor with no values is not an error so should not register as a fail
794  if (optional)
795  {
796  valueStart = nullptr;
797  break;
798  }
799  [[fallthrough]];
800  }
801  default:
802  {
803  VLOG(DRIVER) << __func__ << ": unsupported/invalid operand lifetime:: " << operand.lifetime;
804  valueStart = nullptr;
805  }
806  }
807 
808  return valueStart;
809 }
std::vector<::android::nn::RunTimePoolInfo > m_MemPools
void * GetMemoryFromPool(DataLocation location, const std::vector< android::nn::RunTimePoolInfo > &memPools)
Returns a pointer to a specific location in a pool`.

◆ GetOptionalBool()

bool armnn_driver::GetOptionalBool ( const Operation operation,
uint32_t  inputIndex,
const Model model,
const ConversionData data 
)
inline

Definition at line 890 of file ConversionUtils.hpp.

References ConvertToLayerInputHandle(), g_DontPermute, GetInputOperand(), GetInputPaddingScheme(), GetOperandValueReadOnlyAddress(), GetTensorInt32Values(), OptionalDataLayout(), and SetupAndTrackLayerOutputSlot().

Referenced by Converter::ConvertOperation().

894 {
895  const Operand* operand = GetInputOperand(operation, inputIndex, model);
896  if (!operand)
897  {
898  return false;
899  }
900 
901  if (!IsBool(*operand))
902  {
903  return false;
904  }
905 
906  const void* valueAddress = GetOperandValueReadOnlyAddress(*operand, model, data);
907  if (!valueAddress)
908  {
909  return false;
910  }
911 
912  return *(static_cast<const bool*>(valueAddress));
913 }
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
::android::nn::Operand Operand

◆ GetOptionalConvolutionDilationParams()

bool armnn_driver::GetOptionalConvolutionDilationParams ( const Operation operation,
uint32_t  dilationXIndex,
ConvolutionDescriptor &  descriptor,
const Model model,
const ConversionData data 
)

Definition at line 864 of file ConversionUtils.hpp.

References GetInputScalar().

Referenced by Converter::ConvertOperation().

869 {
870  bool success = true;
871  if (operation.inputs.size() >= dilationXIndex + 2)
872  {
873  success &= GetInputScalar(operation,
874  dilationXIndex,
875  OperandType::INT32,
876  descriptor.m_DilationX,
877  model,
878  data);
879  success &= GetInputScalar(operation,
880  dilationXIndex + 1,
881  OperandType::INT32,
882  descriptor.m_DilationY,
883  model,
884  data);
885  }
886 
887  return success;
888 }
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)

◆ GetOptionalInputActivation()

bool armnn_driver::GetOptionalInputActivation ( const Operation operation,
uint32_t  inputIndex,
ActivationFn &  activationFunction,
const Model model,
const ConversionData data 
)
inline

Definition at line 843 of file ConversionUtils.hpp.

References GetInputActivationFunction().

Referenced by Converter::ConvertOperation().

848 {
849  if (operation.inputs.size() <= inputIndex)
850  {
851  activationFunction = ActivationFn::kActivationNone;
852  }
853  else
854  {
855  if (!GetInputActivationFunction(operation, inputIndex, activationFunction, model, data))
856  {
857  return Fail("%s: Operation has invalid inputs", __func__);
858  }
859  }
860  return true;
861 }
bool GetInputActivationFunction(const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)

◆ GetOutputOperand()

const Operand* armnn_driver::GetOutputOperand ( const Operation operation,
uint32_t  outputIndex,
const Model model 
)
inline

Definition at line 652 of file ConversionUtils.hpp.

References ARMNN_ASSERT, getMainModel(), and GetOperandValueReadOnlyAddress().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), and SetupAndTrackLayerOutputSlot().

655 {
656  if (outputIndex >= operation.outputs.size())
657  {
658  Fail("%s: invalid output index: %i out of %i", __func__, outputIndex, operation.outputs.size());
659  return nullptr;
660  }
661 
662  // Model should have been validated beforehand
663  ARMNN_ASSERT(operation.outputs[outputIndex] < getMainModel(model).operands.size());
664 
665  return &getMainModel(model).operands[operation.outputs[outputIndex]];
666 }
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
const android::nn::Model::Subgraph & getMainModel(const android::nn::Model &model)

◆ GetTensorInfoForOperand()

armnn::TensorInfo GetTensorInfoForOperand ( const Operand operand)

Definition at line 97 of file CanonicalUtils.cpp.

References ARMNN_FALLTHROUGH, armnn::Boolean, armnn::Float16, armnn::Float32, armnn::NotSpecified, armnn::QAsymmS8, armnn::QAsymmU8, armnn::QSymmS16, armnn::QSymmS8, armnn::Scalar, and armnn::Signed32.

Referenced by ConvertOperandToConstTensorPin(), Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), ConvertToLayerInputHandle(), ModelToINetworkTransformer::ModelToINetworkTransformer(), and SetupAndTrackLayerOutputSlot().

98 {
99  using namespace armnn;
100  bool perChannel = false;
101  bool isScalar = false;
102 
103  DataType type;
104  switch (operand.type)
105  {
106  case OperandType::TENSOR_BOOL8:
108  break;
109  case OperandType::TENSOR_FLOAT32:
111  break;
112  case OperandType::TENSOR_FLOAT16:
114  break;
115  case OperandType::TENSOR_QUANT8_ASYMM:
117  break;
118  case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
119  perChannel=true;
121  case OperandType::TENSOR_QUANT8_SYMM:
123  break;
124  case OperandType::TENSOR_QUANT16_SYMM:
126  break;
127  case OperandType::TENSOR_INT32:
129  break;
130  case OperandType::INT32:
132  isScalar = true;
133  break;
134  case OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
136  break;
137  default:
138  throw UnsupportedOperand<OperandType>(operand.type);
139  }
140 
141  TensorInfo ret;
142  if (isScalar)
143  {
145  }
146  else
147  {
148  if (operand.dimensions.size() == 0)
149  {
151  ret = TensorInfo(tensorShape, type);
152  }
153  else
154  {
155  bool dimensionsSpecificity[5] = { true, true, true, true, true };
156  int count = 0;
157  std::for_each(operand.dimensions.data(),
158  operand.dimensions.data() + operand.dimensions.size(),
159  [&](const unsigned int val)
160  {
161  if (val == 0)
162  {
163  dimensionsSpecificity[count] = false;
164  }
165  count++;
166  });
167 
168  TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
169  ret = TensorInfo(tensorShape, type);
170  }
171  }
172 
173  if (perChannel)
174  {
175  // ExtraParams is expected to be of type channelQuant
176  const auto& perAxisQuantParams = std::get<Operand::SymmPerChannelQuantParams>(operand.extraParams);
177 
178  ret.SetQuantizationScales(perAxisQuantParams.scales);
179  ret.SetQuantizationDim(MakeOptional<unsigned int>(perAxisQuantParams.channelDim));
180  }
181  else
182  {
183  ret.SetQuantizationScale(operand.scale);
184  ret.SetQuantizationOffset(operand.zeroPoint);
185  }
186  return ret;
187 }
Copyright (c) 2021 ARM Limited and Contributors.
DataType
Definition: Types.hpp:48
#define ARMNN_FALLTHROUGH
Definition: Utils.hpp:37

◆ GetTensorInt32Values()

bool GetTensorInt32Values ( const Operand operand,
std::vector< int32_t > &  outValues,
const Model model,
const ConversionData data 
)

Definition at line 811 of file ConversionUtils.cpp.

References GetOperandValueReadOnlyAddress().

Referenced by Converter::ConvertOperation(), ConvertPaddings(), ConvertReduce(), and GetOptionalBool().

815 {
816  if (operand.type != OperandType::TENSOR_INT32)
817  {
818  VLOG(DRIVER) << __func__ << ": invalid operand type: " << operand.type;
819  return false;
820  }
821 
822  const void* startAddress = GetOperandValueReadOnlyAddress(operand, model, data);
823  if (!startAddress)
824  {
825  VLOG(DRIVER) << __func__ << ": failed to get operand address " << operand.type;
826  return false;
827  }
828 
829  // Check number of bytes is sensible
830  const uint32_t numBytes = operand.location.length;
831  if (numBytes % sizeof(int32_t) != 0)
832  {
833  return Fail("%s: invalid number of bytes: %i, expected to be a multiple of %i",
834  __func__, numBytes, sizeof(int32_t));
835  }
836 
837  outValues.resize(numBytes / sizeof(int32_t));
838  memcpy(outValues.data(), startAddress, numBytes);
839  return true;
840 }
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)

◆ IsConnectedToDequantize()

bool IsConnectedToDequantize ( armnn::IOutputSlot ioutputSlot)

Definition at line 1026 of file ConversionUtils.cpp.

References armnn::Constant, armnn::Dequantize, IInputSlot::GetConnection(), IConnectableLayer::GetInputSlot(), IOutputSlot::GetOwningIConnectableLayer(), and IConnectableLayer::GetType().

Referenced by Converter::ConvertOperation().

1027 {
1028  VLOG(DRIVER) << "ConversionUtils::IsConnectedToDequantize()";
1029  if (!ioutputSlot)
1030  {
1031  return false;
1032  }
1033  VLOG(DRIVER) << "ConversionUtils::IsConnectedToDequantize() ioutputSlot is valid.";
1034  // Find the connections and layers..
1035  armnn::IConnectableLayer& owningLayer = ioutputSlot->GetOwningIConnectableLayer();
1036  if (owningLayer.GetType() == armnn::LayerType::Dequantize)
1037  {
1038  VLOG(DRIVER) << "ConversionUtils::IsConnectedToDequantize() connected to Dequantize Layer.";
1039  armnn::IInputSlot& inputSlot = owningLayer.GetInputSlot(0);
1040  armnn::IOutputSlot* connection = inputSlot.GetConnection();
1041  if (connection)
1042  {
1043  VLOG(DRIVER) << "ConversionUtils::IsConnectedToDequantize() Dequantize Layer has a connection.";
1044  armnn::IConnectableLayer& connectedLayer =
1045  connection->GetOwningIConnectableLayer();
1046  if (connectedLayer.GetType() == armnn::LayerType::Constant)
1047  {
1048  VLOG(DRIVER) << "ConversionUtils::IsConnectedToDequantize() Dequantize Layer connected to Constant";
1049  return true;
1050  }
1051  }
1052  }
1053  return false;
1054 }
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
An output connection slot for a layer.
Definition: INetwork.hpp:41
virtual const IConnectableLayer & GetOwningIConnectableLayer() const =0
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
virtual const IOutputSlot * GetConnection() const =0
An input connection slot for a layer.
Definition: INetwork.hpp:25

◆ IsDynamicTensor()

bool IsDynamicTensor ( const armnn::TensorInfo tensorInfo)

Checks if a tensor info represents a dynamic tensor.

Definition at line 486 of file CanonicalUtils.cpp.

References TensorShape::AreAllDimensionsSpecified(), TensorShape::GetDimensionality(), TensorInfo::GetNumDimensions(), TensorInfo::GetShape(), and armnn::NotSpecified.

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), ConvertToLayerInputHandle(), and SetupAndTrackLayerOutputSlot().

487 {
489  {
490  return true;
491  }
492  // Account for the usage of the TensorShape empty constructor
493  if (tensorInfo.GetNumDimensions() == 0)
494  {
495  return true;
496  }
497  return !tensorInfo.GetShape().AreAllDimensionsSpecified();
498 }
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
bool AreAllDimensionsSpecified() const
Checks if there is at least one dimension not specified.
Definition: Tensor.cpp:241
Dimensionality GetDimensionality() const
Function that returns the tensor type.
Definition: Tensor.hpp:92
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195

◆ IsOperandConstant()

bool armnn_driver::IsOperandConstant ( const Operand operand)
inline

Definition at line 688 of file ConversionUtils.hpp.

References ConvertOperandToConstTensorPin(), g_DontPermute, and IsWeightsValid().

Referenced by ConvertOperandToConstTensorPin(), Converter::ConvertOperation(), and DequantizeIfRequired().

689 {
690  OperandLifeTime lifetime = operand.lifetime;
691 
692  return lifetime == OperandLifeTime::CONSTANT_COPY ||
693  lifetime == OperandLifeTime::CONSTANT_REFERENCE ||
694  lifetime == OperandLifeTime::POINTER ||
695  lifetime == OperandLifeTime::NO_VALUE;
696 }
::android::nn::Operand::LifeTime OperandLifeTime

◆ IsQSymm8()

bool armnn_driver::IsQSymm8 ( const Operand operand)
inline

Definition at line 992 of file ConversionUtils.hpp.

Referenced by DequantizeIfRequired().

993 {
994  return operand.type == OperandType::TENSOR_QUANT8_SYMM;
995 }

◆ isQuantizedOperand()

bool isQuantizedOperand ( const OperandType operandType)

Definition at line 505 of file CanonicalUtils.cpp.

Referenced by Converter::ConvertOperation().

506 {
507  if (operandType == OperandType::TENSOR_QUANT8_ASYMM ||
508  operandType == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL ||
509  operandType == OperandType::TENSOR_QUANT8_SYMM ||
510  operandType == OperandType::TENSOR_QUANT16_SYMM ||
511  operandType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED)
512  {
513  return true;
514  }
515  else
516  {
517  return false;
518  }
519 }

◆ IsWeightsValid()

bool IsWeightsValid ( const Operation operation,
uint32_t  inputIndex,
const Model model 
)

Utility functions.

Definition at line 134 of file ConversionUtils.cpp.

References GetInputOperand().

Referenced by Converter::ConvertOperation(), and IsOperandConstant().

137 {
138  const Operand* operand = GetInputOperand(operation, inputIndex, model);
139  if (!operand)
140  {
141  Fail("%s: failed to get input operand %i", __func__, inputIndex);
142  return false;
143  }
144 
145  if (operand->lifetime != OperandLifeTime::CONSTANT_COPY
146  && operand->lifetime != OperandLifeTime::CONSTANT_REFERENCE
147  && operand->lifetime != OperandLifeTime::NO_VALUE)
148  {
149  return false;
150  }
151  return true;
152 }
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
::android::nn::Operand Operand

◆ OptionalDataLayout()

armnn::DataLayout OptionalDataLayout ( const Operation operation,
uint32_t  inputIndex,
const Model model,
ConversionData data 
)

Definition at line 842 of file ConversionUtils.cpp.

References GetInputOperand(), GetOperandValueReadOnlyAddress(), armnn::NCHW, and armnn::NHWC.

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), and GetOptionalBool().

846 {
847  const Operand* operand = GetInputOperand(operation, inputIndex, model);
848  if (!operand)
849  {
851  }
852 
853  if (!IsBool(*operand))
854  {
856  }
857 
858  const void* valueAddress = GetOperandValueReadOnlyAddress(*operand, model, data);
859  if (!valueAddress)
860  {
862  }
863 
864  if (*(static_cast<const bool*>(valueAddress)))
865  {
867  }
868  else
869  {
871  }
872 }
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
::android::nn::Operand Operand

◆ ProcessActivation()

armnn::IConnectableLayer * ProcessActivation ( const armnn::TensorInfo tensorInfo,
ActivationFn  activation,
armnn::IConnectableLayer prevLayer,
ConversionData data 
)

Definition at line 874 of file ConversionUtils.cpp.

References ARMNN_ASSERT, armnn::BoundedReLu, IOutputSlot::Connect(), FORWARD_LAYER_SUPPORT_FUNC, IConnectableLayer::GetInputSlot(), IConnectableLayer::GetNumOutputSlots(), IConnectableLayer::GetOutputSlot(), IOutputSlot::GetTensorInfo(), armnn::IsActivationSupported(), ActivationDescriptor::m_A, ActivationDescriptor::m_B, ConversionData::m_Backends, ActivationDescriptor::m_Function, ConversionData::m_Network, armnn::ReLu, IOutputSlot::SetTensorInfo(), armnn::Sigmoid, and armnn::TanH.

Referenced by SetupAndTrackLayerOutputSlot().

878 {
879  ARMNN_ASSERT(prevLayer->GetNumOutputSlots() == 1);
880 
881  prevLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
882 
883  armnn::IConnectableLayer* activationLayer = prevLayer;
884 
885  if (activation != ActivationFn::kActivationNone)
886  {
887  armnn::ActivationDescriptor activationDesc;
888  switch (activation)
889  {
890  case ActivationFn::kActivationRelu:
891  {
893  break;
894  }
895  case ActivationFn::kActivationRelu1:
896  {
898  activationDesc.m_A = 1.0f;
899  activationDesc.m_B = -1.0f;
900  break;
901  }
902  case ActivationFn::kActivationRelu6:
903  {
905  activationDesc.m_A = 6.0f;
906  break;
907  }
908  case ActivationFn::kActivationSigmoid:
909  {
911  break;
912  }
913  case ActivationFn::kActivationTanh:
914  {
916  activationDesc.m_A = 1.0f;
917  activationDesc.m_B = 1.0f;
918  break;
919  }
920  default:
921  {
922  Fail("%s: Invalid activation enum value %i", __func__, activation);
923  return nullptr;
924  }
925  }
926 
927  bool isSupported = false;
930  data.m_Backends,
931  isSupported,
932  prevLayer->GetOutputSlot(0).GetTensorInfo(),
933  tensorInfo,
934  activationDesc);
935  if (!isSupported)
936  {
937  return nullptr;
938  }
939 
940  activationLayer = data.m_Network->AddActivationLayer(activationDesc);
941 
942  prevLayer->GetOutputSlot(0).Connect(activationLayer->GetInputSlot(0));
943  activationLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
944  }
945 
946  return activationLayer;
947 }
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
const std::vector< armnn::BackendId > m_Backends
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:36
min(a, max(b, input)) ReLu1 & ReLu6.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
Definition: Descriptors.hpp:61
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
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
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
Definition: Descriptors.hpp:63
bool IsActivationSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const ActivationDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:59

◆ RenameExportedFiles()

void RenameExportedFiles ( const std::string &  existingSerializedFileName,
const std::string &  existingDotFileName,
const std::string &  dumpDir,
const armnn::NetworkId  networkId 
)

Definition at line 575 of file CanonicalUtils.cpp.

References RenameFile().

Referenced by ArmnnDriverImpl::PrepareArmnnModel().

579 {
580  if (dumpDir.empty())
581  {
582  return;
583  }
584  RenameFile(existingSerializedFileName, std::string("_network.armnn"), dumpDir, networkId);
585  RenameFile(existingDotFileName, std::string("_networkgraph.dot"), dumpDir, networkId);
586 }
void RenameFile(const std::string &existingName, const std::string &extension, const std::string &dumpDir, const armnn::NetworkId networkId)

◆ RenameFile()

void RenameFile ( const std::string &  existingName,
const std::string &  extension,
const std::string &  dumpDir,
const armnn::NetworkId  networkId 
)

Definition at line 588 of file CanonicalUtils.cpp.

Referenced by RenameExportedFiles().

592 {
593  if (existingName.empty() || dumpDir.empty())
594  {
595  return;
596  }
597 
598  fs::path dumpPath = dumpDir;
599  const fs::path newFileName = dumpPath / (std::to_string(networkId) + extension);
600  int iRet = rename(existingName.c_str(), newFileName.c_str());
601  if (iRet != 0)
602  {
603  std::stringstream ss;
604  ss << "rename of [" << existingName << "] to [" << newFileName << "] failed with errno "
605  << std::to_string(errno) << " : " << std::strerror(errno);
606  VLOG(DRIVER) << ss.str().c_str();
607  }
608 }

◆ SerializeNetwork()

std::string SerializeNetwork ( const armnn::INetwork network,
const std::string &  dumpDir,
std::vector< uint8_t > &  dataCacheData,
bool  dataCachingActive 
)

Definition at line 427 of file CanonicalUtils.cpp.

References ISerializer::Create(), and GetFileTimestamp().

Referenced by ArmnnDriverImpl::PrepareArmnnModel().

431 {
432  std::string fileName;
433  bool bSerializeToFile = true;
434  if (dumpDir.empty())
435  {
436  bSerializeToFile = false;
437  }
438  else
439  {
440  std::string timestamp = GetFileTimestamp();
441  if (timestamp.empty())
442  {
443  bSerializeToFile = false;
444  }
445  }
446  if (!bSerializeToFile && !dataCachingActive)
447  {
448  return fileName;
449  }
450 
452  // Serialize the Network
453  serializer->Serialize(network);
454  if (dataCachingActive)
455  {
456  std::stringstream stream;
457  auto serialized = serializer->SaveSerializedToStream(stream);
458  if (serialized)
459  {
460  std::string const serializedString{stream.str()};
461  std::copy(serializedString.begin(),
462  serializedString.end(),
463  std::back_inserter(dataCacheData));
464  }
465  }
466 
467  if (bSerializeToFile)
468  {
469  // Set the name of the output .armnn file.
470  fs::path dumpPath = dumpDir;
471  std::string timestamp = GetFileTimestamp();
472  fs::path tempFilePath = dumpPath / (timestamp + "_network.armnn");
473  fileName = tempFilePath.string();
474 
475  // Save serialized network to a file
476  std::ofstream serializedFile(fileName, std::ios::out | std::ios::binary);
477  auto serialized = serializer->SaveSerializedToStream(serializedFile);
478  if (!serialized)
479  {
480  VLOG(DRIVER) << "An error occurred when serializing to file %s" << fileName.c_str();
481  }
482  }
483  return fileName;
484 }
static ISerializerPtr Create()
Definition: Serializer.cpp:35
std::string GetFileTimestamp()

◆ SetupAndTrackLayerOutputSlot() [1/2]

bool SetupAndTrackLayerOutputSlot ( const Operation operation,
uint32_t  operationOutputIndex,
armnn::IConnectableLayer layer,
uint32_t  layerOutputIndex,
const Model model,
ConversionData data,
const armnn::TensorInfo overrideOutputInfo,
const std::function< void(const armnn::TensorInfo &, bool &)> &  validateFunc,
const ActivationFn &  activationFunction,
bool  inferOutputShapes 
)

Definition at line 949 of file ConversionUtils.cpp.

References IOutputSlot::Disconnect(), IInputSlot::GetConnection(), IConnectableLayer::GetInputSlot(), IConnectableLayer::GetNumInputSlots(), IConnectableLayer::GetNumOutputSlots(), GetOutputOperand(), IConnectableLayer::GetOutputSlot(), IOutputSlot::GetTensorInfo(), GetTensorInfoForOperand(), IsDynamicTensor(), IOutputSlot::IsTensorInfoSet(), ConversionData::m_OutputSlotForOperand, ProcessActivation(), and IOutputSlot::SetTensorInfo().

Referenced by Converter::ConvertOperation(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), GetOptionalBool(), and SetupAndTrackLayerOutputSlot().

959 {
960  const Operand* outputOperand = GetOutputOperand(operation, operationOutputIndex, model);
961  if ((outputOperand == nullptr) || (operationOutputIndex >= layer.GetNumOutputSlots()))
962  {
963  return false;
964  }
965 
966  armnn::IOutputSlot& outputSlot = layer.GetOutputSlot(layerOutputIndex);
967  if (overrideOutputInfo == nullptr)
968  {
969  outputSlot.SetTensorInfo(GetTensorInfoForOperand(*outputOperand));
970  }
971  else
972  {
973  outputSlot.SetTensorInfo(*overrideOutputInfo);
974  }
975 
976  bool isSupported = false;
977  if (validateFunc && (IsDynamicTensor(outputSlot.GetTensorInfo()) || inferOutputShapes))
978  {
979  // Type one dynamic tensors require the previous layer's output shape for inference
980  for (unsigned int inputSlotIndex = 0; inputSlotIndex < layer.GetNumInputSlots(); ++inputSlotIndex)
981  {
982  if(!layer.GetInputSlot(inputSlotIndex).GetConnection())
983  {
984  return false;
985  }
986  }
987  // IsTensorInfoSet will infer the dynamic output shape
988  outputSlot.IsTensorInfoSet();
989  // Once the shape is inferred we can validate it
990  validateFunc(outputSlot.GetTensorInfo(), isSupported);
991 
992  if(!isSupported)
993  {
994  for (unsigned int inputSlotIndex = 0; inputSlotIndex < layer.GetNumInputSlots(); ++inputSlotIndex)
995  {
996  layer.GetInputSlot(inputSlotIndex).GetConnection()->Disconnect(layer.GetInputSlot(inputSlotIndex));
997  }
998  return false;
999  }
1000  }
1001 
1002  const uint32_t operandIndex = operation.outputs[operationOutputIndex];
1003 
1004  if (activationFunction != ActivationFn::kActivationNone)
1005  {
1006  const armnn::TensorInfo& activationOutputInfo = outputSlot.GetTensorInfo();
1007  armnn::IConnectableLayer* const endLayer = ProcessActivation(activationOutputInfo, activationFunction,
1008  &layer, data);
1009 
1010  if (!endLayer)
1011  {
1012  return Fail("%s: ProcessActivation failed", __func__);
1013  }
1014 
1015  armnn::IOutputSlot& activationOutputSlot = endLayer->GetOutputSlot(layerOutputIndex);
1016  data.m_OutputSlotForOperand[operandIndex] = &activationOutputSlot;
1017  }
1018  else
1019  {
1020  data.m_OutputSlotForOperand[operandIndex] = &outputSlot;
1021  }
1022 
1023  return true;
1024 }
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
std::vector< armnn::IOutputSlot * > m_OutputSlotForOperand
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
An output connection slot for a layer.
Definition: INetwork.hpp:41
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
virtual void Disconnect(IInputSlot &slot)=0
bool IsDynamicTensor(const armnn::TensorInfo &tensorInfo)
Checks if a tensor info represents a dynamic tensor.
::android::nn::Operand Operand
virtual bool IsTensorInfoSet() const =0
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
virtual const IOutputSlot * GetConnection() const =0
armnn::IConnectableLayer * ProcessActivation(const armnn::TensorInfo &tensorInfo, ActivationFn activation, armnn::IConnectableLayer *prevLayer, ConversionData &data)
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.

◆ SetupAndTrackLayerOutputSlot() [2/2]

bool armnn_driver::SetupAndTrackLayerOutputSlot ( const Operation operation,
uint32_t  outputIndex,
armnn::IConnectableLayer layer,
const Model model,
ConversionData data,
const armnn::TensorInfo overrideOutputInfo = nullptr,
const std::function< void(const armnn::TensorInfo &, bool &)> &  validateFunc = nullptr,
const ActivationFn &  activationFunction = ActivationFn::kActivationNone 
)
inline

Definition at line 949 of file ConversionUtils.hpp.

References ConvertPaddings(), ConvertPooling2d(), ConvertReduce(), ConvertToActivation(), and SetupAndTrackLayerOutputSlot().

958 {
959  return SetupAndTrackLayerOutputSlot(operation,
960  outputIndex,
961  layer,
962  outputIndex,
963  model,
964  data,
965  overrideOutputInfo,
966  validateFunc,
967  activationFunction);
968 }
bool SetupAndTrackLayerOutputSlot(const Operation &operation, uint32_t outputIndex, armnn::IConnectableLayer &layer, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo=nullptr, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc=nullptr, const ActivationFn &activationFunction=ActivationFn::kActivationNone)

◆ SwizzleAndroidNn4dTensorToArmNn()

void SwizzleAndroidNn4dTensorToArmNn ( armnn::TensorInfo tensorInfo,
const void *  input,
void *  output,
const armnn::PermutationVector mappings 
)

Swizzles tensor data in input according to the dimension mappings.

Definition at line 40 of file CanonicalUtils.cpp.

References armnn::Float16, armnn::Float32, TensorInfo::GetDataType(), armnn::GetDataTypeSize(), TensorInfo::GetNumDimensions(), TensorInfo::GetShape(), armnn::Permute, armnnUtils::Permuted(), armnn::QAsymmS8, armnn::QAsymmU8, and armnn::QSymmS8.

Referenced by ConstTensorPin::ConstTensorPin().

44 {
45  assert(tensorInfo.GetNumDimensions() == 4U);
46 
47  armnn::DataType dataType = tensorInfo.GetDataType();
48  switch (dataType)
49  {
55  // First swizzle tensor info
56  tensorInfo = armnnUtils::Permuted(tensorInfo, mappings);
57  // Then swizzle tensor data
58  armnnUtils::Permute(tensorInfo.GetShape(), mappings, input, output, armnn::GetDataTypeSize(dataType));
59  break;
60  default:
61  VLOG(DRIVER) << "Unknown armnn::DataType for swizzling";
62  assert(0);
63  }
64 }
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:131
DataType
Definition: Types.hpp:48
DataType GetDataType() const
Definition: Tensor.hpp:198
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:98
constexpr unsigned int GetDataTypeSize(DataType dataType)
Definition: TypesUtils.hpp:151

Variable Documentation

◆ g_DontPermute