From 462728090eac533e3122080a86129541df128fe3 Mon Sep 17 00:00:00 2001 From: Mike Kelly Date: Wed, 14 Aug 2019 17:00:48 +0100 Subject: IVGCVSW-3633 Refactor HalPolicy to fully support V1.2 models * Templated and moved V1.0 and V1.1 Convert methods to ensure they can work with later versions of models, operations and operands. * The V1.2 HalPolicy no longer converts V1.2 models, operations and operands to earlier versions. * The V1.2 HalPolicy no longer passes operations to the V1.1 or V1.0 HalPolicies for conversion. Signed-off-by: Mike Kelly Change-Id: I5de59d43a3abb1f8ac0253dc637ad68318960c76 --- 1.1/HalPolicy.cpp | 374 +----------------------------------------------------- 1 file changed, 5 insertions(+), 369 deletions(-) (limited to '1.1') diff --git a/1.1/HalPolicy.cpp b/1.1/HalPolicy.cpp index e75b5c2a..aa650e90 100644 --- a/1.1/HalPolicy.cpp +++ b/1.1/HalPolicy.cpp @@ -106,61 +106,7 @@ bool HalPolicy::ConvertOperation(const Operation& operation, const Model& model, bool HalPolicy::ConvertDiv(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_1::HalPolicy::ConvertDiv()"); - - LayerInputHandle input0 = ConvertToLayerInputHandle(operation, 0, model, data); - LayerInputHandle input1 = ConvertToLayerInputHandle(operation, 1, model, data); - - if (!input0.IsValid() || !input1.IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - // The FuseActivation parameter is always the input index 2 - // and it should be optional - ActivationFn activationFunction; - if (!GetOptionalInputActivation(operation, 2, activationFunction, model, data)) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const Operand* output = GetOutputOperand(operation, 0, model); - if (!output) - { - return Fail("%s: Could not read output 0", __func__); - } - - const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDivisionSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outputInfo); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* const startLayer = data.m_Network->AddDivisionLayer(); - armnn::IConnectableLayer* const endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); - - const armnn::TensorInfo& inputTensorInfo0 = input0.GetTensorInfo(); - const armnn::TensorInfo& inputTensorInfo1 = input1.GetTensorInfo(); - - if (endLayer) - { - BroadcastTensor(input0, input1, startLayer, *data.m_Network); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data); - } - - return Fail("%s: ProcessActivation failed", __func__); + return ::ConvertDiv(operation, model, data); } bool HalPolicy::ConvertSub(const Operation& operation, const Model& model, ConversionData& data) @@ -172,75 +118,7 @@ bool HalPolicy::ConvertSub(const Operation& operation, const Model& model, Conve bool HalPolicy::ConvertMean(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_1::HalPolicy::ConvertMean()"); - - LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data); - if (!input.IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const Operand* output = GetOutputOperand(operation, 0, model); - if (!output) - { - return Fail("%s: Could not read output 0", __func__); - } - - const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - - const Operand* axisOperand = GetInputOperand(operation, 1, model); - if (!axisOperand) - { - return Fail("%s: Could not read input 1", __func__); - } - - std::vector axis; - if (!GetTensorInt32Values(*axisOperand, axis, model, data)) - { - return Fail("%s: Input 1 has invalid values", __func__); - } - - const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); - - // Convert the axis to unsigned int and remove duplicates. - unsigned int rank = inputInfo.GetNumDimensions(); - std::set uniqueAxis; - std::transform(axis.begin(), axis.end(), - std::inserter(uniqueAxis, uniqueAxis.begin()), - [rank](int i) -> unsigned int { return (i + rank) % rank; }); - - // Get the "keep dims" flag. - int32_t keepDims = 0; - if (!GetInputInt32(operation, 2, keepDims, model, data)) - { - return Fail("%s: Could not read input 2", __func__); - } - - armnn::MeanDescriptor descriptor; - descriptor.m_Axis.assign(uniqueAxis.begin(), uniqueAxis.end()); - descriptor.m_KeepDims = keepDims > 0; - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsMeanSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* const layer = data.m_Network->AddMeanLayer(descriptor); - assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - - return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); + return ::ConvertMean(operation, model, data); } bool HalPolicy::ConvertPad(const Operation& operation, const Model& model, ConversionData& data) @@ -258,261 +136,19 @@ bool HalPolicy::ConvertSpaceToBatchNd(const Operation& operation, const Model& m bool HalPolicy::ConvertSqueeze(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_1::HalPolicy::ConvertSqueeze()"); - - LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data); - if (!input.IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); - unsigned int rank = inputInfo.GetNumDimensions(); - if (rank > 4) - { - Fail("%s: Inputs with rank greater than 4 are not supported", __func__); - } - - const Operand* output = GetOutputOperand(operation, 0, model); - if (!output) - { - return Fail("%s: Could not read output 0", __func__); - } - - if (IsDynamicTensor(GetTensorInfoForOperand(*output))) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - - // NOTE: Axis is an optional parameter to SQUEEZE, therefore we do not want to generate a failure - // if the operand index is out of bounds. - const Operand* axisOperand = GetInputOperand(operation, 1, model, false); - - const uint32_t dimensionSequence[] = { 0, 1, 2, 3 }; - - std::vector axis; - if (!axisOperand) - { - axis.assign(dimensionSequence, - dimensionSequence + rank); - } - else - { - GetTensorInt32Values(*axisOperand, axis, model, data); - } - - - std::vector outputDims; - for (unsigned int i = 0; i < rank; i++) - { - bool skipSqueeze = (std::find(axis.begin(), axis.end(), i) == axis.end()); - auto currentDimension = inputInfo.GetShape()[i]; - if (skipSqueeze || currentDimension != 1) - { - outputDims.push_back(currentDimension); - } - } - - armnn::TensorShape outShape = armnn::TensorShape(outputDims.size(), outputDims.data()); - - armnn::TensorInfo outputInfo = inputInfo; - outputInfo.SetShape(outShape); - - armnn::ReshapeDescriptor reshapeDesc; - reshapeDesc.m_TargetShape = outputInfo.GetShape(); - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsReshapeSupported, - data.m_Backends, - isSupported, - inputInfo, - reshapeDesc); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* const layer = data.m_Network->AddReshapeLayer(reshapeDesc); - assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - - return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); + return ::ConvertSqueeze(operation, model, data); } bool HalPolicy::ConvertStridedSlice(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_1::HalPolicy::ConvertStridedSlice()"); - - LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data); - if (!input.IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); - unsigned int rank = inputInfo.GetNumDimensions(); - if (rank > 4) - { - Fail("%s: Inputs with rank greater than 4 are not supported", __func__); - } - - const Operand* output = GetOutputOperand(operation, 0, model); - if (!output) - { - return Fail("%s: Could not read output 0", __func__); - } - - const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - - const Operand* beginOperand = GetInputOperand(operation, 1, model); - const Operand* endOperand = GetInputOperand(operation, 2, model); - const Operand* stridesOperand = GetInputOperand(operation, 3, model); - - std::vector beginValues; - std::vector endValues; - std::vector stridesValues; - - // The length of the beginOperand, endOperand and stridesOperand must be of a rank(input) - auto ValidateInputOperands = [&] (const Operand& operand, std::vector& operandValues) - { - if (!GetTensorInt32Values(operand, operandValues, model, data)) - { - return false; - } - - if (operandValues.size() != rank) - { - return false; - } - - return true; - }; - - if (!ValidateInputOperands(*beginOperand, beginValues) - || !ValidateInputOperands(*endOperand, endValues) - || !ValidateInputOperands(*stridesOperand, stridesValues)) - { - return Fail("%s: Operation has invalid input operand", __func__); - } - - // Stride cannot have value '0' - if (std::any_of(stridesValues.cbegin(), stridesValues.cend(), [](int32_t i){ return i == 0; })) - { - return Fail("%s: Stride must be non-zero value.", __func__); - } - - armnn::StridedSliceDescriptor descriptor; - descriptor.m_Begin.assign(beginValues.cbegin(), beginValues.cend()); - descriptor.m_End.assign(endValues.cbegin(), endValues.cend()); - descriptor.m_Stride.assign(stridesValues.cbegin(), stridesValues.cend()); - descriptor.m_DataLayout = armnn::DataLayout::NHWC; - - // Get the "begin_mask", "end_mask", and "shrink_axis_mask" flags - if (!GetInputInt32(operation, 4, descriptor.m_BeginMask, model, data) || - !GetInputInt32(operation, 5, descriptor.m_EndMask, model, data) || - !GetInputInt32(operation, 6, descriptor.m_ShrinkAxisMask, model, data)) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsStridedSliceSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* const layer = data.m_Network->AddStridedSliceLayer(descriptor); - assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - - return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); + return ::ConvertStridedSlice(operation, model, data); } bool HalPolicy::ConvertTranspose(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_1::HalPolicy::ConvertTranspose()"); - - LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data); - if (!input.IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); - unsigned int rank = inputInfo.GetNumDimensions(); - if (rank > 4) - { - Fail("%s: Inputs with rank greater than 4 are not supported", __func__); - } - - // NOTE: Axis is an optional parameter to TRANSPOSE, therefore we do not want to generate a failure - // if the operand index is out of bounds. - const Operand* permOperand = GetInputOperand(operation, 1, model, false); - - std::vector perm(rank); - if (!permOperand) - { - // NOTE: If perm is not given, it is set to (n-1...0), where n is the rank of the tensor - for (unsigned int i = rank; i > 0; i--) - { - perm[rank - i] = boost::numeric_cast (i - 1); - } - } - else - { - GetTensorInt32Values(*permOperand, perm, model, data); - } - - std::vector outputDims(perm.begin(), perm.begin() + rank); - - auto permutationVector = armnn::PermutationVector(outputDims.data(), outputDims.size()); - if (!permutationVector.IsEqual(NHWCToArmNN) - && !permutationVector.IsEqual(ArmNNToNHWC) - && !permutationVector.IsEqual({ 3, 2, 0, 1 })) - { - return Fail("%s: Only [0, 3, 1, 2], [0, 2, 3, 1] and [3, 2, 0, 1] permutations are supported.", __func__); - } - - armnn::PermuteDescriptor permuteDesc; - permuteDesc.m_DimMappings = permutationVector; - - const Operand* output = GetOutputOperand(operation, 0, model); - if (!output) - { - return Fail("%s: Could not read output 0", __func__); - } - - const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsPermuteSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - permuteDesc); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* const layer = data.m_Network->AddPermuteLayer(permuteDesc); - assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - - return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); + return ::ConvertTranspose(operation, model, data); } bool HalPolicy::ConvertBatchToSpaceNd(const Operation& operation, const Model& model, ConversionData& data) -- cgit v1.2.1