From fcf2a15b0b4aa44530dc56c7a13bc685c687f87a Mon Sep 17 00:00:00 2001 From: Kevin May Date: Tue, 8 Sep 2020 16:06:32 +0100 Subject: IVGCVSW-5245 Support Fused Activations for Dynamic Tensors * Move ProcessActivation from Convert to SetupAndTrackLayerOutputSlot by passing optional ActivationFn * Connect Activation after IsTensorInfoSet() is called Signed-off-by: Kevin May Change-Id: I472bcb65b12ae6e934bd1e9af8a6f6aceb311c0e --- ConversionUtils.hpp | 157 +++++++++++++++++++++--------------------------- ConversionUtils_1_2.hpp | 44 +++----------- ConversionUtils_1_3.hpp | 3 +- 3 files changed, 79 insertions(+), 125 deletions(-) diff --git a/ConversionUtils.hpp b/ConversionUtils.hpp index fa67f791..450b91f2 100644 --- a/ConversionUtils.hpp +++ b/ConversionUtils.hpp @@ -1400,6 +1400,7 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, ConversionData& data, const armnn::TensorInfo* overrideOutputInfo = nullptr, const std::function & validateFunc = nullptr, + const ActivationFn& activationFunction = ActivationFn::kActivationNone, bool inferOutputShapes = false) { using HalOperand = typename HalPolicy::Operand; @@ -1447,7 +1448,25 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, } const uint32_t operandIndex = operation.outputs[operationOutputIndex]; - data.m_OutputSlotForOperand[operandIndex] = &outputSlot; + + if (activationFunction != ActivationFn::kActivationNone) + { + const armnn::TensorInfo& activationOutputInfo = outputSlot.GetTensorInfo(); + armnn::IConnectableLayer* const endLayer = ProcessActivation(activationOutputInfo, activationFunction, + &layer, data); + + if (!endLayer) + { + return Fail("%s: ProcessActivation failed", __func__); + } + + armnn::IOutputSlot& activationOutputSlot = endLayer->GetOutputSlot(layerOutputIndex); + data.m_OutputSlotForOperand[operandIndex] = &activationOutputSlot; + } + else + { + data.m_OutputSlotForOperand[operandIndex] = &outputSlot; + } return true; } @@ -1498,7 +1517,8 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, const HalModel& model, ConversionData& data, const armnn::TensorInfo* overrideOutputInfo = nullptr, - const std::function & validateFunc = nullptr) + const std::function & validateFunc = nullptr, + const ActivationFn& activationFunction = ActivationFn::kActivationNone) { return SetupAndTrackLayerOutputSlot(operation, outputIndex, @@ -1507,7 +1527,8 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, model, data, overrideOutputInfo, - validateFunc); + validateFunc, + activationFunction); } templateGetInputSlot(0)); if (!isSupported) @@ -1795,7 +1810,8 @@ bool ConvertPooling2d(const HalOperation& operation, return false; } - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *pooling2dLayer, model, + data, nullptr, validateFunc, activation); } templateAddAdditionLayer(); - armnn::IConnectableLayer* const endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); - if (endLayer != nullptr) + bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); + if (!isReshapeSupported) { - bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); - if (!isReshapeSupported) - { - return false; - } - - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); - } - else - { - return Fail("%s: ProcessActivation failed", __func__); + return false; } + + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activationFunction); + } templateGetInputSlot(0)); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activation); } templateGetInputSlot(0)); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activation); } templateAddDivisionLayer(); - armnn::IConnectableLayer* const endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); - if (endLayer) + bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); + if (!isReshapeSupported) { - bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); - if (!isReshapeSupported) - { - return false; - } - - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return false; } - return Fail("%s: ProcessActivation failed", __func__); + + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activationFunction); + } templateAddFullyConnectedLayer(desc, weights, armnn::Optional(bias)); - armnn::IConnectableLayer* endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); - if (endLayer != nullptr) + if (inputInfo.GetNumDimensions() > 2U) { - if (inputInfo.GetNumDimensions() > 2U) - { - armnn::ReshapeDescriptor reshapeDescriptor; - reshapeDescriptor.m_TargetShape = reshapedInfo.GetShape(); - - armnn::IConnectableLayer* reshapeLayer = data.m_Network->AddReshapeLayer(reshapeDescriptor); - assert(reshapeLayer != nullptr); - input.Connect(reshapeLayer->GetInputSlot(0)); - reshapeLayer->GetOutputSlot(0).SetTensorInfo(reshapedInfo); - reshapeLayer->GetOutputSlot(0).Connect(startLayer->GetInputSlot(0)); - } - else - { - input.Connect(startLayer->GetInputSlot(0)); - } + armnn::ReshapeDescriptor reshapeDescriptor; + reshapeDescriptor.m_TargetShape = reshapedInfo.GetShape(); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + armnn::IConnectableLayer* reshapeLayer = data.m_Network->AddReshapeLayer(reshapeDescriptor); + assert(reshapeLayer != nullptr); + input.Connect(reshapeLayer->GetInputSlot(0)); + reshapeLayer->GetOutputSlot(0).SetTensorInfo(reshapedInfo); + reshapeLayer->GetOutputSlot(0).Connect(startLayer->GetInputSlot(0)); } else { - return Fail("%s: ProcessActivation failed", __func__); + input.Connect(startLayer->GetInputSlot(0)); } + + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activationFunction); } templateAddMultiplicationLayer(); - armnn::IConnectableLayer* const endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); const armnn::TensorInfo& inputTensorInfo0 = input0.GetTensorInfo(); const armnn::TensorInfo& inputTensorInfo1 = input1.GetTensorInfo(); - if (endLayer != nullptr) - { - bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); - if (!isReshapeSupported) - { - return false; - } - - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); - } - else + bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); + if (!isReshapeSupported) { - return Fail("%s: ProcessActivation failed", __func__); + return false; } + + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activationFunction); } templateAddSubtractionLayer(); - armnn::IConnectableLayer* const endLayer = ProcessActivation(outputInfo, activationFunction, startLayer, data); const armnn::TensorInfo& inputTensorInfo0 = input0.GetTensorInfo(); const armnn::TensorInfo& inputTensorInfo1 = input1.GetTensorInfo(); - if (endLayer) + bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); + if (!isReshapeSupported) { - bool isReshapeSupported = BroadcastTensor(input0, input1, startLayer, data); - if (!isReshapeSupported) - { - return false; - } - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return false; } - - return Fail("%s: ProcessActivation failed", __func__); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activationFunction); } templateGetInputSlot(0)); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activation); } templateGetInputSlot(0)); - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activation); } templateGetOutputSlot(0).SetTensorInfo(outputInfo); - // - // Set up Activation layer (if it is set) - // - IConnectableLayer* endLayer = ProcessActivation(outputInfo, activation, concatLayer, data); - if (!endLayer) - { - return Fail("%s: ProcessActivation failed", __func__); - } - - return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *concatLayer, model, + data, nullptr, validateFunc, activation); } template(operation, 0, *layer, 0, model, data) && SetupAndTrackLayerOutputSlot( - operation, 1, *layer, 1, model, data, nullptr, validateFunc, true)); + operation, 1, *layer, 1, model, data, nullptr, validateFunc, ActivationFn::kActivationNone, true)); } } @@ -2656,7 +2637,7 @@ bool ConvertLstm(const HalOperation& operation, const HalModel& model, Conversio SetupAndTrackLayerOutputSlot(operation, 1, *layer, 1, model, data) && SetupAndTrackLayerOutputSlot(operation, 2, *layer, 2, model, data) && SetupAndTrackLayerOutputSlot( - operation, 3, *layer, 3, model, data, nullptr, validateFunc, true)); + operation, 3, *layer, 3, model, data, nullptr, validateFunc, ActivationFn::kActivationNone, true)); } } @@ -2851,15 +2832,10 @@ bool ConvertTransposeConv2d(const HalOperation& operation, const HalModel& model return Fail("%s: AddTransposeConvolution2dLayer failed", __func__); } - 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, nullptr, validateFunc); + return SetupAndTrackLayerOutputSlot(operation, 0, *startLayer, model, + data, nullptr, validateFunc, activation); } } // armnn_driver namespace \ No newline at end of file diff --git a/ConversionUtils_1_3.hpp b/ConversionUtils_1_3.hpp index 445b9ea7..a7f00fc3 100644 --- a/ConversionUtils_1_3.hpp +++ b/ConversionUtils_1_3.hpp @@ -654,7 +654,8 @@ bool ConvertQuantizedLstm(const HalOperation& operation, const HalModel& model, return ( SetupAndTrackLayerOutputSlot( operation, 0, *layer, 0, model, data, &constOutputStateOutInfo) && SetupAndTrackLayerOutputSlot( - operation, 1, *layer, 1, model, data, nullptr, validateFunc, true) && + operation, 1, *layer, 1, model, data, nullptr, validateFunc, + ActivationFn::kActivationNone, true) && SetupAndTrackLayerOutputSlot(operation, 2, *layer, 2, model, data, &constOutputInfo)); } } -- cgit v1.2.1