From b8805204fb0ea64079735921bcc0cc2b1aedfcf6 Mon Sep 17 00:00:00 2001 From: Mike Kelly Date: Wed, 31 Jul 2019 17:25:43 +0100 Subject: IVGCVSW-3601 Fix skipped VTS Concatenate Tests * Fixed Skipped VTS Concatenate Tests. Signed-off-by: Mike Kelly Change-Id: I29e7dcdedefc0e9c54f86fa5de23aa714c469585 --- 1.0/HalPolicy.cpp | 227 +----------------------------------------------------- 1 file changed, 1 insertion(+), 226 deletions(-) (limited to '1.0') diff --git a/1.0/HalPolicy.cpp b/1.0/HalPolicy.cpp index a3c0e63b..6c8dcb5d 100644 --- a/1.0/HalPolicy.cpp +++ b/1.0/HalPolicy.cpp @@ -142,232 +142,7 @@ bool HalPolicy::ConvertAveragePool2d(const Operation& operation, const Model& mo bool HalPolicy::ConvertConcatenation(const Operation& operation, const Model& model, ConversionData& data) { ALOGV("hal_1_0::HalPolicy::ConvertConcatenation()"); - - // The first N (0..N-1) inputs are tensors. The Nth input is the concatenation axis. - if (operation.inputs.size() <= 1) - { - return Fail("%s: Operation has insufficient arguments", __func__); - } - - // Get inputs and outputs - const std::size_t numInputTensors = operation.inputs.size() - 1; - - int32_t concatDim; - if (!GetInputScalar(operation, numInputTensors, OperandType::INT32, concatDim, model, data)) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - const Operand* const outputOperand = GetOutputOperand(operation, 0, model); - if (!outputOperand) - { - return Fail("%s: Operation has no outputs", __func__); - } - - - armnn::TensorInfo outputInfo = GetTensorInfoForOperand(*outputOperand); - armnn::TensorShape outputShape = outputInfo.GetShape(); - - // - // handle negative concat dims along the lines of tensorflow as described here: - // https://www.tensorflow.org/api_docs/python/tf/concat - // "negative axis refers to axis + rank(values)-th dimension" - // - if (concatDim < 0) - { - concatDim += outputShape.GetNumDimensions(); - } - - if (concatDim >= static_cast(outputShape.GetNumDimensions()) || concatDim < 0) - { - return Fail("%s: Operation has invalid concat axis: %d", __func__, concatDim); - } - - std::vector inputHandles; - std::vector inputShapes; - - inputHandles.reserve(numInputTensors); - inputShapes.reserve(numInputTensors); - - bool inputsHaveBeenReshaped = false; - unsigned int tensorDimensionsAdded = 0; - - for (uint32_t i = 0; i < numInputTensors; ++i) - { - const Operand* const operand = GetInputOperand(operation, i, model); - if (!operand) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - - armnn::TensorShape operandShape = GetTensorShapeForOperand(*operand); - LayerInputHandle operandInputHandle = - ConvertToLayerInputHandle(operation, i, model, data); - - if (operandShape.GetNumDimensions() == 0) - { - return Fail("%s: Operands with rank 0 are not supported", __func__); - } - - if (RequiresReshape(operandShape)) - { - inputsHaveBeenReshaped = true; - - armnn::TensorInfo reshapeInfo = operandInputHandle.GetTensorInfo(); - - // Expand the tensor to three dimensions - if (operandShape.GetNumDimensions() == 2) - { - reshapeInfo.SetShape(armnn::TensorShape({1, operandShape[0], operandShape[1]})); - tensorDimensionsAdded = 1; - } - else - { - reshapeInfo.SetShape(armnn::TensorShape({1, 1, operandShape[0]})); - tensorDimensionsAdded = 2; - } - - armnn::IConnectableLayer& newReshape = AddReshapeLayer( - *data.m_Network, - operandInputHandle, - reshapeInfo - ); - - // Point to the reshape operation rather then the input operation - operandShape = reshapeInfo.GetShape(); - operandInputHandle = LayerInputHandle(true, &newReshape.GetOutputSlot(0), reshapeInfo); - } - - inputShapes.emplace_back(operandShape); - inputHandles.emplace_back(operandInputHandle); - - if (!inputHandles.back().IsValid()) - { - return Fail("%s: Operation has invalid inputs", __func__); - } - } - - BOOST_ASSERT(inputShapes.size() == inputHandles.size()); - - if (inputsHaveBeenReshaped) - { - // Adjust the concatenation dimension by the amount of dimensions added (if any) - concatDim += tensorDimensionsAdded; - - // Add extra dimensions to the output shape to reflect the addition of the reshape layers - if (tensorDimensionsAdded == 1) - { - outputShape = armnn::TensorShape({1, outputShape[0], outputShape[1]}); - } - else if (tensorDimensionsAdded == 2) - { - outputShape = armnn::TensorShape({1, 1, outputShape[0]}); - } - } - - // Check if permutations is required and get the pair of permutations required for the concatenation. - // Permutation is required when the concat dimension is 2 for a 4D tensor or 1 for a 3D tensor. - std::pair permutationPair = - std::make_pair(IdentityPermutation4D, IdentityPermutation4D); - - bool needPermute = - CreateConcatPermutationParameters(inputShapes[0].GetNumDimensions(), concatDim, permutationPair); - - if (needPermute) - { - outputShape = armnnUtils::Permuted(outputShape, permutationPair.first); - } - - outputInfo.SetShape(outputShape); - - // this is no-op for identity swizzles, otherwise it replaces both - // the handles and shapes with the swizzled layer output handles and shapes - SwizzleInputs(*data.m_Network, inputHandles, inputShapes, permutationPair.first); - - // Create an armnn concat layer descriptor - this will also perform validation on the input shapes - armnn::OriginsDescriptor concatDescriptor; - - try - { - // The concat descriptor is always created across the only supported concat dimension - // which is 0, 1 or 3 for a 4-D tensor, or 0 or 2 for a 3-D tensor. - concatDescriptor = - armnn::CreateDescriptorForConcatenation(inputShapes.begin(), inputShapes.end(), concatDim); - } - catch (const armnn::Exception& error) - { - return Fail("%s: Error preparing concat descriptor. %s", __func__, error.what()); - } - - // Validate the output shape is correct given the input shapes based on the - // only valid concat dimension which is 0, 1 or 3 for a 4-D tensor, or 0 or 2 for a 3-D tensor. - if (!ValidateConcatOutputShape(inputShapes, outputShape, concatDim)) - { - return Fail("%s: Error validating the output shape for concat", __func__); - } - - std::vector inputTensorInfos; - std::transform(inputHandles.begin(), inputHandles.end(), std::back_inserter(inputTensorInfos), - [](const LayerInputHandle& h) -> const armnn::TensorInfo*{ return &h.GetTensorInfo(); }); - - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsConcatSupported, - data.m_Backends, - isSupported, - inputTensorInfos, - outputInfo, - concatDescriptor); - if (!isSupported) - { - return false; - } - - armnn::IConnectableLayer* layer = data.m_Network->AddConcatLayer(concatDescriptor); - assert(layer != nullptr); - layer->GetOutputSlot(0).SetTensorInfo(outputInfo); - - // Connect inputs to the layer - const int numInputSlots = layer->GetNumInputSlots(); - assert(static_cast(numInputSlots) == inputHandles.size()); - for (int i = 0; i < numInputSlots; ++i) - { - // connect the input directly to the merge (concat) layer - inputHandles[static_cast(i)].Connect(layer->GetInputSlot(i)); - } - - if (needPermute) - { - // Add permutation layer and connect the output to it, the permutation becomes the output layer - armnn::IConnectableLayer& deswizzleLayer = AddPermuteLayer(*data.m_Network, - layer->GetOutputSlot(0), - permutationPair.second); - layer = &deswizzleLayer; - } - - if (inputsHaveBeenReshaped) - { - armnn::TensorInfo afterConcatInfo = layer->GetOutputSlot(0).GetTensorInfo(); - - // Undo the reshape knowing the amount of dimensions added - if (tensorDimensionsAdded == 1) - { - afterConcatInfo.SetShape(armnn::TensorShape({ afterConcatInfo.GetShape()[1], - afterConcatInfo.GetShape()[2] })); - } - else if (tensorDimensionsAdded == 2) - { - afterConcatInfo.SetShape(armnn::TensorShape({ afterConcatInfo.GetShape()[2] })); - } - - layer = &AddReshapeLayer( - *data.m_Network, - layer->GetOutputSlot(0), - afterConcatInfo - ); - } - - return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); + return ::ConvertConcatenation(operation, model, data); } bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, ConversionData& data) -- cgit v1.2.1