17 : m_OutputSlot(nullptr)
22 : m_OutputSlot(outputSlot)
24 , m_TensorInfo(tensorInfo)
37 m_OutputSlot->
Connect(inputSlot);
63 SanitizeBiasQuantizationScale(biasInfo, weightInfo, inputInfo);
65 m_TensorInfo = biasInfo;
76 : m_Optional(optional)
80 const void* valueStart,
88 VLOG(DRIVER) <<
"The size of ConstTensor does not match its TensorInfo.";
91 const bool needsSwizzling = (mappings.
GetSize() > 0);
94 m_SwizzledTensorData.resize(tensorInfo.
GetNumBytes());
117 return m_ConstTensor;
124 return &m_ConstTensor;
141 Fail(
"%s: failed to get input operand %i", __func__, inputIndex);
145 if (operand->lifetime != OperandLifeTime::CONSTANT_COPY
146 && operand->lifetime != OperandLifeTime::CONSTANT_REFERENCE
147 && operand->lifetime != OperandLifeTime::NO_VALUE)
162 if (!IsOperandTypeSupportedForTensors(operand.type))
164 VLOG(DRIVER) << __func__ <<
": unsupported operand type for tensor" << operand.type;
170 VLOG(DRIVER) << __func__ <<
": lifetime for input tensor: r" << operand.lifetime;
183 Fail(
"%s: failed to get operand address", __func__);
189 if (overrideTensorShape)
191 tensorInfo.
SetShape(*overrideTensorShape);
194 if (overrideDataType)
201 return ConstTensorPin(tensorInfo, valueStart, operand.location.length, dimensionMappings);
215 Fail(
"%s: failed to get input operand %i", __func__, inputIndex);
219 if (!IsOperandTypeSupportedForTensors(operand->type))
221 VLOG(DRIVER) << __func__ <<
": unsupported operand type for tensor: " << operand->type;
233 const uint32_t operandIndex = operation.inputs[inputIndex];
243 Fail(
"%s: Type 2 dynamic input tensors are not supported", __func__);
248 switch (operand->lifetime)
250 case OperandLifeTime::SUBGRAPH_INPUT:
254 bool isInputSupported =
false;
261 if (!isInputSupported)
263 Fail(
"%s: unsupported input tensor", __func__);
267 [[clang::fallthrough]];
269 case OperandLifeTime::TEMPORARY_VARIABLE:
270 case OperandLifeTime::SUBGRAPH_OUTPUT:
276 const uint32_t operandIndex = operation.inputs[inputIndex];
279 case OperandLifeTime::CONSTANT_COPY:
280 case OperandLifeTime::POINTER:
281 case OperandLifeTime::CONSTANT_REFERENCE:
283 auto constantTensorDataType = operandTensorInfo.
GetDataType();
291 &constantTensorDataType);
294 bool isSupported =
false;
315 Fail(
"%s: invalid operand tensor", __func__);
322 VLOG(DRIVER) << __func__ <<
": unsupported lifetime for input tensor: " << operand->lifetime;
329 VLOG(DRIVER) << __func__ <<
": Operand type: " << e.
m_type <<
" not supported in ArmnnDriver";
341 if (!paddingsOperand)
343 return Fail(
"%s: Could not read paddings operand", __func__);
349 return Fail(
"%s: Operation has invalid paddings operand: expected shape [%d, 2]", __func__, rank);
352 std::vector<int32_t> paddings;
355 return Fail(
"%s: Operation has invalid or unsupported paddings operand", __func__);
359 for (
unsigned int i = 0; i < paddings.size() - 1; i += 2)
361 int paddingBeforeInput = paddings[i];
362 int paddingAfterInput = paddings[i + 1];
364 if (paddingBeforeInput < 0 || paddingAfterInput < 0)
366 return Fail(
"%s: Operation has invalid paddings operand, invalid padding values.", __func__);
369 padDescriptor.
m_PadList.emplace_back((
unsigned int) paddingBeforeInput, (
unsigned int) paddingAfterInput);
377 const char* operationName,
383 VLOG(DRIVER) <<
"Converter::ConvertL2Pool2d()";
388 return Fail(
"%s: Operation Could not read input 0", operationName);
394 return Fail(
"%s: Could not read output 0", __func__);
405 ActivationFn activation;
407 auto inputSize = operation.inputs.size();
422 return Fail(
"%s: Operation has invalid inputs", operationName);
425 if (Is12OrLaterOperand(*output))
433 ::android::nn::PaddingScheme scheme;
441 return Fail(
"%s: Operation has invalid inputs", operationName);
444 if (Is12OrLaterOperand(*output))
457 bool isSupported =
false;
477 validateFunc(outputInfo, isSupported);
488 return Fail(
"%s: AddPooling2dLayer failed", __func__);
499 data,
nullptr, validateFunc, activation);
513 return Fail(
"%s: Operation has invalid inputs", __func__);
520 return Fail(
"%s: Could not read output 0", __func__);
527 return Fail(
"%s: Could not read input 1", __func__);
529 std::vector<int32_t> axis;
532 return Fail(
"%s: Input 1 has invalid values", __func__);
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());
546 return Fail(
"%s: Could not read input 2", __func__);
549 bool isSupported =
false;
563 validateFunc(outputInfo, isSupported);
576 assert(layer !=
nullptr);
584 const char* operationName,
592 return Fail(
"%s: Input 0 is invalid", operationName);
603 bool isSupported =
false;
622 validateFunc(outInfo, isSupported);
654 const size_t weightsInputIndex = operation.inputs[operand_index];
658 for (uint32_t operationIdx = 0; operationIdx <
getMainModel(model).operations.size(); ++operationIdx)
661 const auto& operationIt =
getMainModel(model).operations[operationIdx];
662 if (operationIt.type != OperationType::DEQUANTIZE)
667 size_t outOpIndex = weightsInputIndex + 1;
668 for (
size_t i = 0; outOpIndex != weightsInputIndex && i < operationIt.outputs.size(); ++i)
670 outOpIndex = operationIt.outputs[i];
673 if (outOpIndex != weightsInputIndex)
695 const uint8_t* quantizedBuffer =
reinterpret_cast<const uint8_t*
>(startValue);
696 size_t dequantizedBufferLength = operand->location.length;
697 const float quantizationScale = operand->scale;
699 auto dequantizedBuffer = std::make_unique<float[]>(dequantizedBufferLength + 1);
700 for (
size_t i = 0; i < dequantizedBufferLength; ++i)
702 float* dstPtr = dequantizedBuffer.get();
704 *dstPtr++ = quantizedBuffer[i] * quantizationScale;
709 operand->dimensions.data(),
712 return { std::move(dequantizedBuffer), dequantizedBufferLength *
sizeof(float),
713 std::move(tensorInfo),
739 operation, operandIndex, model, data,
g_DontPermute,
nullptr, optional);
745 std::get<2>(dequantized), std::get<0>(dequantized).
get(), std::get<1>(dequantized),
g_DontPermute);
752 PaddingScheme& outPaddingScheme,
756 int32_t paddingSchemeAsInt;
757 if (!
GetInputInt32(operation, inputIndex, paddingSchemeAsInt, model, data))
759 return Fail(
"%s: failed to get padding scheme input value", __func__);
762 outPaddingScheme =
static_cast<::android::nn::PaddingScheme
>(paddingSchemeAsInt);
771 const void* valueStart =
nullptr;
772 switch (operand.lifetime)
774 case OperandLifeTime::CONSTANT_COPY:
776 valueStart = model.operandValues.data() + operand.location.offset;
779 case OperandLifeTime::POINTER:
782 valueStart = std::get<const void*>(operand.location.pointer);
785 case OperandLifeTime::CONSTANT_REFERENCE:
791 case OperandLifeTime::NO_VALUE:
796 valueStart =
nullptr;
803 VLOG(DRIVER) << __func__ <<
": unsupported/invalid operand lifetime:: " << operand.lifetime;
804 valueStart =
nullptr;
812 std::vector<int32_t>& outValues,
816 if (operand.type != OperandType::TENSOR_INT32)
818 VLOG(DRIVER) << __func__ <<
": invalid operand type: " << operand.type;
825 VLOG(DRIVER) << __func__ <<
": failed to get operand address " << operand.type;
830 const uint32_t numBytes = operand.location.length;
831 if (numBytes %
sizeof(int32_t) != 0)
833 return Fail(
"%s: invalid number of bytes: %i, expected to be a multiple of %i",
834 __func__, numBytes,
sizeof(int32_t));
837 outValues.resize(numBytes /
sizeof(int32_t));
838 memcpy(outValues.data(), startAddress, numBytes);
853 if (!IsBool(*operand))
864 if (*(static_cast<const bool*>(valueAddress)))
875 ActivationFn activation,
885 if (activation != ActivationFn::kActivationNone)
890 case ActivationFn::kActivationRelu:
895 case ActivationFn::kActivationRelu1:
898 activationDesc.
m_A = 1.0f;
899 activationDesc.
m_B = -1.0f;
902 case ActivationFn::kActivationRelu6:
905 activationDesc.
m_A = 6.0f;
908 case ActivationFn::kActivationSigmoid:
913 case ActivationFn::kActivationTanh:
916 activationDesc.
m_A = 1.0f;
917 activationDesc.
m_B = 1.0f;
922 Fail(
"%s: Invalid activation enum value %i", __func__, activation);
927 bool isSupported =
false;
940 activationLayer = data.
m_Network->AddActivationLayer(activationDesc);
946 return activationLayer;
950 uint32_t operationOutputIndex,
952 uint32_t layerOutputIndex,
957 const ActivationFn& activationFunction,
958 bool inferOutputShapes)
961 if ((outputOperand ==
nullptr) || (operationOutputIndex >= layer.
GetNumOutputSlots()))
967 if (overrideOutputInfo ==
nullptr)
976 bool isSupported =
false;
980 for (
unsigned int inputSlotIndex = 0; inputSlotIndex < layer.
GetNumInputSlots(); ++inputSlotIndex)
994 for (
unsigned int inputSlotIndex = 0; inputSlotIndex < layer.
GetNumInputSlots(); ++inputSlotIndex)
1002 const uint32_t operandIndex = operation.outputs[operationOutputIndex];
1004 if (activationFunction != ActivationFn::kActivationNone)
1012 return Fail(
"%s: ProcessActivation failed", __func__);
1028 VLOG(DRIVER) <<
"ConversionUtils::IsConnectedToDequantize()";
1033 VLOG(DRIVER) <<
"ConversionUtils::IsConnectedToDequantize() ioutputSlot is valid.";
1038 VLOG(DRIVER) <<
"ConversionUtils::IsConnectedToDequantize() connected to Dequantize Layer.";
1043 VLOG(DRIVER) <<
"ConversionUtils::IsConnectedToDequantize() Dequantize Layer has a connection.";
1048 VLOG(DRIVER) <<
"ConversionUtils::IsConnectedToDequantize() Dequantize Layer connected to Constant";
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified...
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
std::vector<::android::nn::RunTimePoolInfo > m_MemPools
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.
bool IsQSymm8(const Operand &operand)
uint32_t m_PadBottom
Padding bottom value in the height dimension.
std::vector< armnn::IOutputSlot * > m_OutputSlotForOperand
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
unsigned int GetWidthIndex() const
const TensorShape & GetShape() const
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.
bool ConvertReduce(const Operation &operation, const Model &model, ConversionData &data, armnn::ReduceOperation reduceOperation)
::android::nn::Operation Operation
bool m_KeepDims
if true then output shape has no change.
void * GetMemoryFromPool(DataLocation location, const std::vector< android::nn::RunTimePoolInfo > &memPools)
Returns a pointer to a specific location in a pool`.
unsigned int GetNumBytes() const
const armnn::ConstTensor * GetConstTensorPtr() const
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)
unsigned int GetNumElements() const
uint32_t m_PadTop
Padding top value in the height dimension.
MemoryType GetMemoryArea() const
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
ReduceOperation m_ReduceOperation
Specifies the reduction operation to execute.
void IgnoreUnused(Ts &&...)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
bool m_DynamicInputsEncountered
unsigned int GetHeightIndex() const
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
void SetShape(const TensorShape &newShape)
const armnn::PermutationVector g_DontPermute
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
void SwizzleAndroidNn4dTensorToArmNn(armnn::TensorInfo &tensorInfo, const void *input, void *output, const armnn::PermutationVector &mappings)
Swizzles tensor data in input according to the dimension mappings.
uint32_t m_PoolHeight
Pooling height value.
bool AreDynamicTensorsSupported()
Checks for ArmNN support of dynamic tensors.
A PadDescriptor for the PadLayer.
bool ConvertPooling2d(const Operation &operation, const char *operationName, armnn::PoolingAlgorithm poolType, const Model &model, ConversionData &data)
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)
::android::nn::Model Model
Helper classes.
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)
armnn::INetworkPtr m_Network
An output connection slot for a layer.
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...
DataType GetDataType() const
A ReduceDescriptor for the REDUCE operators.
armnn::TensorInfo GetTensorInfoForOperand(const Operand &operand)
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
virtual void Disconnect(IInputSlot &slot)=0
bool ConvertPaddings(const Operation &operation, const Model &model, ConversionData &data, unsigned int rank, armnn::PadDescriptor &padDescriptor)
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
virtual const IConnectableLayer & GetOwningIConnectableLayer() const =0
#define ARMNN_ASSERT(COND)
An ActivationDescriptor for the ActivationLayer.
const TensorInfo & GetInfo() const
min(a, max(b, input)) ReLu1 & ReLu6.
void SetDataType(DataType type)
ConstTensorPin(bool optional=false)
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
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.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< uint32_t > m_vAxis
The indices of the dimensions to reduce.
bool IsWeightsValid(const Operation &operation, uint32_t inputIndex, const Model &model)
Utility functions.
std::tuple< std::unique_ptr< float[]>, size_t, armnn::TensorInfo, DequantizeStatus > DequantizeResult
bool IsInputSupported(const BackendId &backend, const TensorInfo &input, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
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)
const android::nn::Model::Subgraph & getMainModel(const android::nn::Model &model)
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)
bool ConvertToActivation(const Operation &operation, const char *operationName, const armnn::ActivationDescriptor &activationDesc, const Model &model, ConversionData &data)
ConstTensorPin DequantizeAndMakeConstTensorPin(const Operation &operation, const Model &model, const ConversionData &data, size_t operandIndex, bool optional)
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported,...)
bool GetInputInt32(const Operation &operation, uint32_t inputIndex, int32_t &outValue, const Model &model, const ConversionData &data)
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
bool IsConnectedToDequantize(armnn::IOutputSlot *ioutputSlot)
const armnn::ConstTensor & GetConstTensor() const
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
virtual bool IsTensorInfoSet() const =0
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
armnn::IConnectableLayer * ProcessActivation(const armnn::TensorInfo &tensorInfo, ActivationFn activation, armnn::IConnectableLayer *prevLayer, ConversionData &data)
bool IsOperandConstant(const Operand &operand)
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
DequantizeResult DequantizeIfRequired(size_t operand_index, const Operation &operation, const Model &model, const ConversionData &data)
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.
bool IsConstantSupported(const BackendId &backend, const TensorInfo &output, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
virtual int Connect(IInputSlot &destination)=0
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.
unsigned int GetNumDimensions() const
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
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).
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.