From d2966a96822772683f4b4a8a368edd3ee8adfdad Mon Sep 17 00:00:00 2001 From: Ferran Balaguer Date: Fri, 26 Oct 2018 16:41:17 +0100 Subject: MLCE-65 Early access release with NHWC for Android Change-Id: I612efc41b5ea460f4893bb05b8d358d21ee393bb --- 1.0/HalPolicy.cpp | 111 ++++++++++++++++++++++++++-------------------------- ConversionUtils.hpp | 35 ++++++++--------- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/1.0/HalPolicy.cpp b/1.0/HalPolicy.cpp index 4c5fba3f..e4193e31 100644 --- a/1.0/HalPolicy.cpp +++ b/1.0/HalPolicy.cpp @@ -354,11 +354,8 @@ bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, Co const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - const armnn::TensorInfo swizzledInputInfo = armnnUtils::Permuted(inputInfo, NHWCToArmNN); - const armnn::TensorInfo swizzledOutputInfo = armnnUtils::Permuted(outputInfo, NHWCToArmNN); - // ArmNN does not currently support non-fixed weights or bias - const ConstTensorPin weightsPin = ConvertOperationInputToConstTensorPin(operation, 1, model, data, NHWCToArmNN); + const ConstTensorPin weightsPin = ConvertOperationInputToConstTensorPin(operation, 1, model, data); const ConstTensorPin biasPin = ConvertOperationInputToConstTensorPin(operation, 2, model, data); if (!weightsPin.IsValid() || !biasPin.IsValid()) @@ -368,9 +365,10 @@ bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, Co armnn::ConstTensor weights = weightsPin.GetConstTensor(); armnn::ConstTensor bias = biasPin.GetConstTensor(); - SanitizeBiasQuantizationScale(bias.GetInfo(), weights.GetInfo(), swizzledInputInfo); + SanitizeBiasQuantizationScale(bias.GetInfo(), weights.GetInfo(), inputInfo); armnn::Convolution2dDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NHWC; ActivationFn activation; if (operation.inputs.size() == 10) @@ -397,10 +395,10 @@ bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, Co return Fail("%s: Operation has invalid inputs", __func__); } - const uint32_t kernelX = weights.GetShape()[3]; - const uint32_t kernelY = weights.GetShape()[2]; - const uint32_t inputX = swizzledInputInfo.GetShape()[3]; - const uint32_t inputY = swizzledInputInfo.GetShape()[2]; + const uint32_t kernelX = weights.GetShape()[2]; + const uint32_t kernelY = weights.GetShape()[1]; + const uint32_t inputX = inputInfo.GetShape()[2]; + const uint32_t inputY = inputInfo.GetShape()[1]; CalcPadding(inputX, kernelX, desc.m_StrideX, desc.m_PadLeft, desc.m_PadRight, paddingScheme); CalcPadding(inputY, kernelY, desc.m_StrideY, desc.m_PadTop, desc.m_PadBottom, paddingScheme); @@ -416,8 +414,8 @@ bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, Co if (!IsLayerSupported(__func__, armnn::IsConvolution2dSupported, data.m_Compute, - swizzledInputInfo, - swizzledOutputInfo, + inputInfo, + outputInfo, desc, weights.GetInfo(), biases)) @@ -426,18 +424,20 @@ bool HalPolicy::ConvertConv2d(const Operation& operation, const Model& model, Co } armnn::IConnectableLayer* startLayer = data.m_Network->AddConvolution2dLayer(desc, weights, bias); - armnn::IConnectableLayer* endLayer = ProcessActivation(swizzledOutputInfo, activation, startLayer, data); - - if (endLayer != nullptr) + if (!startLayer) { - armnn::IConnectableLayer& outSwizzleLayer = - SwizzleInDeswizzleOut(*data.m_Network, input, *startLayer, *endLayer); - return SetupAndTrackLayerOutputSlot(operation, 0, outSwizzleLayer, model, data); + return Fail("%s: AddConvolution2dLayer failed", __func__); } - else + + armnn::IConnectableLayer* endLayer = ProcessActivation(outputInfo, activation, startLayer, data); + if (!endLayer) { return Fail("%s: ProcessActivation failed", __func__); } + + input.Connect(startLayer->GetInputSlot(0)); + + return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data); } bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& model, ConversionData& data) @@ -457,13 +457,10 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - const armnn::TensorInfo swizzledInputInfo = armnnUtils::Permuted(inputInfo, NHWCToArmNN); - const armnn::TensorInfo swizzledOutputInfo = armnnUtils::Permuted(outputInfo, NHWCToArmNN); - // ArmNN does not currently support non-fixed weights or bias // Find the shape of the weights tensor. In AndroidNN this will be [ 1, H, W, I * M ] - // but in ArmNN it needs to be [ M, I, H, W ] + // which is equal to [ M, H, W, I ] const Operand* weightsOperand = GetInputOperand(operation, 1, model); if (weightsOperand == nullptr) @@ -476,10 +473,10 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& inputInfo.GetShape()[3], weightsOperand->dimensions[3] / inputInfo.GetShape()[3] }); - // Swizzle weight data [ H, W, I, M ] -> [ M, I, H, W ] - const armnn::PermutationVector HWIMToMIHW = { 2U, 3U, 1U, 0U }; + // Swizzle weight data [ H, W, I, M ] -> [ M, H, W, I ] + const armnn::PermutationVector HWIMToMHWI = { 1U, 2U, 3U, 0U }; ConstTensorPin weightsPin = - ConvertOperationInputToConstTensorPin(operation, 1, model, data, HWIMToMIHW, &weightsShape); + ConvertOperationInputToConstTensorPin(operation, 1, model, data, HWIMToMHWI, &weightsShape); // Bias is a 1D tensor ConstTensorPin biasPin = ConvertOperationInputToConstTensorPin(operation, 2, model, data); @@ -491,19 +488,20 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& armnn::ConstTensor weights = weightsPin.GetConstTensor(); armnn::ConstTensor bias = biasPin.GetConstTensor(); - SanitizeBiasQuantizationScale(bias.GetInfo(), weights.GetInfo(), swizzledInputInfo); + SanitizeBiasQuantizationScale(bias.GetInfo(), weights.GetInfo(), inputInfo); armnn::DepthwiseConvolution2dDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NHWC; ActivationFn activation; if (operation.inputs.size() == 11) { - if (!GetInputScalar(operation, 3, OperandType::INT32, desc.m_PadLeft, model, data) || - !GetInputScalar(operation, 4, OperandType::INT32, desc.m_PadRight, model, data) || - !GetInputScalar(operation, 5, OperandType::INT32, desc.m_PadTop, model, data) || - !GetInputScalar(operation, 6, OperandType::INT32, desc.m_PadBottom, model, data) || - !GetInputScalar(operation, 7, OperandType::INT32, desc.m_StrideX, model, data) || - !GetInputScalar(operation, 8, OperandType::INT32, desc.m_StrideY, model, data) || + if (!GetInputScalar(operation, 3, OperandType::INT32, desc.m_PadLeft, model, data) || + !GetInputScalar(operation, 4, OperandType::INT32, desc.m_PadRight, model, data) || + !GetInputScalar(operation, 5, OperandType::INT32, desc.m_PadTop, model, data) || + !GetInputScalar(operation, 6, OperandType::INT32, desc.m_PadBottom, model, data) || + !GetInputScalar(operation, 7, OperandType::INT32, desc.m_StrideX, model, data) || + !GetInputScalar(operation, 8, OperandType::INT32, desc.m_StrideY, model, data) || !GetInputActivationFunction(operation, 10, activation, model, data)) { return Fail("%s: Operation has invalid inputs", __func__); @@ -512,18 +510,18 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& else if (operation.inputs.size() == 8) { android::nn::PaddingScheme paddingScheme; - if (!GetInputPaddingScheme(operation, 3, paddingScheme, model, data) || - !GetInputScalar(operation, 4, OperandType::INT32, desc.m_StrideX, model, data) || - !GetInputScalar(operation, 5, OperandType::INT32, desc.m_StrideY, model, data) || + if (!GetInputPaddingScheme(operation, 3, paddingScheme, model, data) || + !GetInputScalar(operation, 4, OperandType::INT32, desc.m_StrideX, model, data) || + !GetInputScalar(operation, 5, OperandType::INT32, desc.m_StrideY, model, data) || !GetInputActivationFunction(operation, 7, activation, model, data)) { return Fail("%s: Operation has invalid inputs", __func__); } - const uint32_t kernelX = weights.GetShape()[3]; - const uint32_t kernelY = weights.GetShape()[2]; - const uint32_t inputX = swizzledInputInfo.GetShape()[3]; - const uint32_t inputY = swizzledInputInfo.GetShape()[2]; + const uint32_t kernelX = weights.GetShape()[2]; + const uint32_t kernelY = weights.GetShape()[1]; + const uint32_t inputX = inputInfo.GetShape()[2]; + const uint32_t inputY = inputInfo.GetShape()[1]; CalcPadding(inputX, kernelX, desc.m_StrideX, desc.m_PadLeft, desc.m_PadRight, paddingScheme); CalcPadding(inputY, kernelY, desc.m_StrideY, desc.m_PadTop, desc.m_PadBottom, paddingScheme); @@ -539,8 +537,8 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& if (!IsLayerSupported(__func__, armnn::IsDepthwiseConvolutionSupported, data.m_Compute, - swizzledInputInfo, - swizzledOutputInfo, + inputInfo, + outputInfo, desc, weights.GetInfo(), biases)) @@ -549,18 +547,20 @@ bool HalPolicy::ConvertDepthwiseConv2d(const Operation& operation, const Model& } armnn::IConnectableLayer* startLayer = data.m_Network->AddDepthwiseConvolution2dLayer(desc, weights, bias); - armnn::IConnectableLayer* endLayer = ProcessActivation(swizzledOutputInfo, activation, startLayer, data); - - if (endLayer != nullptr) + if (!startLayer) { - armnn::IConnectableLayer& outSwizzleLayer = - SwizzleInDeswizzleOut(*data.m_Network, input, *startLayer, *endLayer); - return SetupAndTrackLayerOutputSlot(operation, 0, outSwizzleLayer, model, data); + return Fail("%s: AddDepthwiseConvolution2dLayer failed", __func__); } - else + + armnn::IConnectableLayer* endLayer = ProcessActivation(outputInfo, activation, startLayer, data); + if (!endLayer) { return Fail("%s: ProcessActivation failed", __func__); } + + input.Connect(startLayer->GetInputSlot(0)); + + return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data); } bool HalPolicy::ConvertFloor(const Operation& operation, const Model& model, ConversionData& data) @@ -1324,18 +1324,17 @@ bool HalPolicy::ConvertResizeBilinear(const Operation& operation, const Model& m const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - const armnn::TensorInfo swizzledInputInfo = armnnUtils::Permuted(inputInfo, NHWCToArmNN); - const armnn::TensorInfo swizzledOutputInfo = armnnUtils::Permuted(outputInfo, NHWCToArmNN); if (!IsLayerSupported(__func__, armnn::IsResizeBilinearSupported, data.m_Compute, - swizzledInputInfo)) + inputInfo)) { return false; } armnn::ResizeBilinearDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NHWC; if ( !GetInputScalar(operation, 1, OperandType::INT32, desc.m_TargetHeight, model, data) || !GetInputScalar(operation, 2, OperandType::INT32, desc.m_TargetWidth, model, data)) @@ -1344,12 +1343,14 @@ bool HalPolicy::ConvertResizeBilinear(const Operation& operation, const Model& m } armnn::IConnectableLayer* layer = data.m_Network->AddResizeBilinearLayer(desc); - assert(layer != nullptr); - layer->GetOutputSlot(0).SetTensorInfo(swizzledOutputInfo); + if (!layer) + { + return Fail("%s: AddResizeBilinearLayer failed to execute", __func__); + } - armnn::IConnectableLayer& outSwizzleLayer = SwizzleInDeswizzleOut(*data.m_Network, input, *layer); + input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot(operation, 0, outSwizzleLayer, model, data); + return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data); } diff --git a/ConversionUtils.hpp b/ConversionUtils.hpp index 783f7cec..9b56a9aa 100644 --- a/ConversionUtils.hpp +++ b/ConversionUtils.hpp @@ -939,10 +939,8 @@ bool ConvertPooling2d(const HalOperation& operation, const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - const armnn::TensorInfo swizzledInputInfo = armnnUtils::Permuted(inputInfo, NHWCToArmNN); - const armnn::TensorInfo swizzledOutputInfo = armnnUtils::Permuted(outputInfo, NHWCToArmNN); - armnn::Pooling2dDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NHWC; desc.m_PoolType = poolType; desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor; @@ -962,8 +960,8 @@ bool ConvertPooling2d(const HalOperation& operation, return Fail("%s: Operation has invalid inputs", operationName); } - const unsigned int inputWidth = swizzledInputInfo.GetShape()[3]; - const unsigned int inputHeight = swizzledInputInfo.GetShape()[2]; + const unsigned int inputWidth = inputInfo.GetShape()[2]; + const unsigned int inputHeight = inputInfo.GetShape()[1]; CalcPadding(inputWidth, desc.m_PoolWidth, desc.m_StrideX, desc.m_PadLeft, desc.m_PadRight, scheme); CalcPadding(inputHeight, desc.m_PoolHeight, desc.m_StrideY, desc.m_PadTop, desc.m_PadBottom, scheme); @@ -985,32 +983,31 @@ bool ConvertPooling2d(const HalOperation& operation, } } - armnn::IConnectableLayer* startLayer = nullptr; - if (!IsLayerSupported(__func__, armnn::IsPooling2dSupported, data.m_Compute, - swizzledInputInfo, - swizzledOutputInfo, + inputInfo, + outputInfo, desc)) { return false; } - startLayer = data.m_Network->AddPooling2dLayer(desc); - - armnn::IConnectableLayer* endLayer = ProcessActivation(swizzledOutputInfo, activation, startLayer, data); - - if (endLayer != nullptr) + armnn::IConnectableLayer* startLayer = data.m_Network->AddPooling2dLayer(desc); + if (!startLayer) { - armnn::IConnectableLayer& outSwizzleLayer = - SwizzleInDeswizzleOut(*data.m_Network, input, *startLayer, *endLayer); - return SetupAndTrackLayerOutputSlot(operation, 0, outSwizzleLayer, model, data); + return Fail("%s: AddPooling2dLayer failed", __func__); } - else + + armnn::IConnectableLayer* endLayer = ProcessActivation(outputInfo, activation, startLayer, data); + if (!endLayer) { - return Fail("%s: ProcessActivation failed", operationName); + return Fail("%s: ProcessActivation failed", __func__); } + + input.Connect(startLayer->GetInputSlot(0)); + + return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data); } } // namespace armnn_driver -- cgit v1.2.1