// // Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "LayersFwd.hpp" #include #include #include #include #include TEST_SUITE("Optimizer") { using namespace armnn; using namespace armnn::optimizations; // Helpers for testing auto checkConstantFloat32 = [](const armnn::Layer *const layer) { return IsLayerOfType(layer) && (layer->GetDataType() == DataType::Float32); }; auto checkConstantFloat16 = [](const armnn::Layer *const layer) { return IsLayerOfType(layer) && (layer->GetDataType() == DataType::Float16); }; auto checkConstantQAsymmS8 = [](const armnn::Layer *const layer) { return IsLayerOfType(layer) && (layer->GetDataType() == DataType::QAsymmS8); }; auto checkPadFoldedIntoConv2d = [](const Layer* const layer) { const auto conv2dLayer = static_cast(layer); const auto conv2dLayerParams = conv2dLayer->GetParameters(); return IsLayerOfType(layer) && (layer->GetNameStr() == "folded-pad-into-conv2d") && (conv2dLayerParams.m_PadLeft == 2) && (conv2dLayerParams.m_PadRight == 2) && (conv2dLayerParams.m_PadTop == 2) && (conv2dLayerParams.m_PadBottom == 2) && (conv2dLayerParams.m_StrideX == 1) && (conv2dLayerParams.m_StrideY == 1) && (conv2dLayerParams.m_BiasEnabled == false) && (conv2dLayerParams.m_DataLayout == DataLayout::NHWC); }; TEST_CASE("ConvertConstFloat16DequantizeToConstFloat32") { Graph graph; const unsigned int shape[] = {1, 2, 2, 3}; const TensorInfo constTensorInfo(4, shape, DataType::Float16, 1.0, 0, true); const TensorInfo outputDequantizeInfo(4, shape, DataType::Float32, 1.0, 0, true); auto constantLayer = graph.AddLayer("constant"); std::vector constantValues(constTensorInfo.GetNumElements(), 4.5f); ConstTensor constTensor(constTensorInfo, constantValues.data()); constantLayer->m_LayerOutput = std::make_shared(constTensor); constantLayer->GetOutputSlot().SetTensorInfo(constTensorInfo); auto dequantizeLayer = graph.AddLayer("dequantize"); dequantizeLayer->GetOutputSlot().SetTensorInfo(outputDequantizeInfo); auto output = graph.AddLayer(0, "output"); // Connect up constant -> dequantize -> output constantLayer->GetOutputSlot().Connect(dequantizeLayer->GetInputSlot(0)); dequantizeLayer->GetOutputSlot().Connect(output->GetInputSlot(0)); CHECK(CheckSequence(graph.cbegin(), graph.cend(), checkConstantFloat16, &IsLayerOfType, &IsLayerOfType)); armnn::Optimizer::Pass(graph, MakeOptimizations(ConvertConstDequantisationLayersToConstLayers())); CHECK(CheckSequence(graph.cbegin(), graph.cend(), checkConstantFloat32, &IsLayerOfType)); } TEST_CASE("ConvertConstFloat16DequantizeToConstFloat32PlusFusePadWithConv2d") { Graph graph; const unsigned int shape[] = {1, 2, 2, 3}; const TensorInfo constTensorInfo(4, shape, DataType::Float16, 1.0, 0, true); const TensorInfo outputDequantizeInfo(4, shape, DataType::Float32, 1.0, 0, true); auto constantLayer = graph.AddLayer("constant"); std::vector constantValues(constTensorInfo.GetNumElements(), 4.5f); ConstTensor constTensor(constTensorInfo, constantValues.data()); constantLayer->m_LayerOutput = std::make_shared(constTensor); constantLayer->GetOutputSlot().SetTensorInfo(constTensorInfo); auto dequantizeLayer = graph.AddLayer("dequantize"); dequantizeLayer->GetOutputSlot().SetTensorInfo(outputDequantizeInfo); auto output = graph.AddLayer(0, "output"); Convolution2dDescriptor convolution2dDescriptor; convolution2dDescriptor.m_BiasEnabled = false; convolution2dDescriptor.m_StrideX = 1; convolution2dDescriptor.m_StrideY = 1; convolution2dDescriptor.m_DataLayout = DataLayout::NHWC; auto conv2d = graph.AddLayer(convolution2dDescriptor, "conv2d"); auto inputLayer = graph.AddLayer(0, "input"); PadDescriptor padDescriptor({{0, 0}, {2, 2}, {2, 2}, {0, 0}}); const unsigned int paddedShape[] = {1, 6, 6, 3}; TensorInfo paddedInfo(4, paddedShape, DataType::Float32); auto padLayer = graph.AddLayer(padDescriptor, "pad"); padLayer->GetOutputSlot().SetTensorInfo(paddedInfo); // Connect up: // input -> pad -> conv2d -> output // constant -> dequantize -> constantLayer->GetOutputSlot().Connect(dequantizeLayer->GetInputSlot(0)); dequantizeLayer->GetOutputSlot().Connect(conv2d->GetInputSlot(1)); inputLayer->GetOutputSlot().Connect(padLayer->GetInputSlot(0)); padLayer->GetOutputSlot().Connect(conv2d->GetInputSlot(0)); conv2d->GetOutputSlot().Connect(output->GetInputSlot(0)); CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType, checkConstantFloat16, &IsLayerOfType, &IsLayerOfType, &IsLayerOfType, &IsLayerOfType)); armnn::Optimizer::Pass(graph, MakeOptimizations(ConvertConstDequantisationLayersToConstLayers())); armnn::Optimizer::Pass(graph, MakeOptimizations(FoldPadIntoConvolution2d())); // Ensure that the const and dequantize are now constant of type fp32 // Ensure pad and conv2d are now just convolution CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType, checkConstantFloat32, checkPadFoldedIntoConv2d, &IsLayerOfType)); } TEST_CASE("ConvertConstInt8DequantizeToConstFloat32") { Graph graph; const unsigned int shape[] = {1, 2, 2, 3}; const TensorInfo constTensorInfo(4, shape, DataType::QAsymmS8, 1.0, 0, true); const TensorInfo outputDequantizeInfo(4, shape, DataType::Float32, 1.0, 0, true); auto constantLayer = graph.AddLayer("constant"); std::vector constantValues(constTensorInfo.GetNumElements(), 5); ConstTensor constTensor(constTensorInfo, constantValues.data()); constantLayer->m_LayerOutput = std::make_shared(constTensor); constantLayer->GetOutputSlot().SetTensorInfo(constTensorInfo); auto dequantizeLayer = graph.AddLayer("dequantize"); dequantizeLayer->GetOutputSlot().SetTensorInfo(outputDequantizeInfo); auto output = graph.AddLayer(0, "output"); // Connect up constant -> dequantize -> output constantLayer->GetOutputSlot().Connect(dequantizeLayer->GetInputSlot(0)); dequantizeLayer->GetOutputSlot().Connect(output->GetInputSlot(0)); CHECK(CheckSequence(graph.cbegin(), graph.cend(), checkConstantQAsymmS8, &IsLayerOfType, &IsLayerOfType)); armnn::Optimizer::Pass(graph, MakeOptimizations(ConvertConstDequantisationLayersToConstLayers())); CHECK(CheckSequence(graph.cbegin(), graph.cend(), checkConstantFloat32, &IsLayerOfType)); } }