diff options
author | Ryan OShea <ryan.oshea3@arm.com> | 2023-07-25 14:28:27 +0100 |
---|---|---|
committer | ryan.oshea3 <ryan.oshea3@arm.com> | 2023-08-02 14:25:26 +0000 |
commit | b4c493430567bff25e61e9df0dbab554c29f635d (patch) | |
tree | 9d9fa320c25f5aa9f89aafb8b9b8b6c071990161 /src/armnn/test | |
parent | 083802d04b7a4499c4daba860c57e4f152f9c060 (diff) | |
download | armnn-b4c493430567bff25e61e9df0dbab554c29f635d.tar.gz |
IVGCVSW-7880 Add check for FP16 backend support
* Check if preferred backends have FP16 support before enable fp16-turbo-mode
* Unit tests
* Replaced global gpuAccCapabilities with getter method construction
* Replaced deprecated function call in SL shim
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Signed-off-by: Ryan OShea <ryan.oshea3@arm.com>
Change-Id: If29b62b330ca8987de8acf6408db11daf25ca0b5
Diffstat (limited to 'src/armnn/test')
-rw-r--r-- | src/armnn/test/optimizations/Fp32NetworkToFp16ConverterTests.cpp | 288 |
1 files changed, 287 insertions, 1 deletions
diff --git a/src/armnn/test/optimizations/Fp32NetworkToFp16ConverterTests.cpp b/src/armnn/test/optimizations/Fp32NetworkToFp16ConverterTests.cpp index 0a4a4fafde..90f94bccbf 100644 --- a/src/armnn/test/optimizations/Fp32NetworkToFp16ConverterTests.cpp +++ b/src/armnn/test/optimizations/Fp32NetworkToFp16ConverterTests.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -7,6 +7,12 @@ #include <Optimizer.hpp> +#if defined(ARMNNREF_ENABLED) +#include <CommonTestUtils.hpp> +#include <GraphUtils.hpp> +#include <backendsCommon/test/mockBackend/MockImportBackend.hpp> +#endif + #include <doctest/doctest.h> TEST_SUITE("Optimizer") @@ -50,4 +56,284 @@ TEST_CASE("Fp32NetworkToFp16OptimizationTest") CHECK(floor->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float16); } +#if defined(ARMNNREF_ENABLED) +TEST_CASE("ReduceFp32ToFp16EnabledBackendHasFp16SupportTest") +{ + using namespace armnn; + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); + IConnectableLayer* input2 = net->AddInputLayer(2, "input2"); + IConnectableLayer* add = net->AddElementwiseBinaryLayer(BinaryOperation::Add, "add"); + IConnectableLayer* sub = net->AddElementwiseBinaryLayer(BinaryOperation::Sub, "sub"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); + input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); + input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0)); + add->GetOutputSlot(0).Connect(sub->GetInputSlot(1)); + sub->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32); + + input0->GetOutputSlot(0).SetTensorInfo(info); + input1->GetOutputSlot(0).SetTensorInfo(info); + input2->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); + sub->GetOutputSlot(0).SetTensorInfo(info); + + std::vector<BackendId> backends = { Compute::CpuRef }; + + // optimize the network + OptimizerOptionsOpaque optOptions; + optOptions.SetReduceFp32ToFp16(true); + IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions); + + Graph& graph = GetGraphForTesting(optNet.get()); + + // Layers are added to convert the inputs to FP16 + CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::ConvertFp16ToFp32Layer>, + &IsLayerOfType<armnn::OutputLayer>)); + + Layer* const addLayer = GetFirstLayerWithName(graph, "add"); + Layer* const subLayer = GetFirstLayerWithName(graph, "sub"); + + CHECK(addLayer->GetDataType() == armnn::DataType::Float16); + CHECK(addLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float16); + CHECK(addLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float16); + + CHECK(subLayer->GetDataType() == armnn::DataType::Float16); + CHECK(subLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float16); + CHECK(subLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float16); +} + +TEST_CASE("ReduceFp32ToFp16EnabledBackendNoFp16SupportTest") +{ + using namespace armnn; + + // Create a mock backend without FP16 support + MockImportBackendInitialiser initialiser; // Register the Mock Backend + auto backendObjPtr = CreateBackendObject(MockImportBackendId()); + CHECK((backendObjPtr != nullptr)); + + BackendIdSet backendIds = BackendRegistryInstance().GetBackendIds(); + if (backendIds.find("MockRef") == backendIds.end()) + { + std::string message = "Cannot load MockRef"; + FAIL(message); + } + + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); + IConnectableLayer* add = net->AddElementwiseBinaryLayer(BinaryOperation::Add, "add"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); + input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); + add->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32); + + input0->GetOutputSlot(0).SetTensorInfo(info); + input1->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); + + std::vector<BackendId> backends = { "MockRef" }; + + // optimize the network + OptimizerOptionsOpaque optOptions; + optOptions.SetReduceFp32ToFp16(true); + IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions); + + Graph& graph = GetGraphForTesting(optNet.get()); + + // Do not add layers to convert the inputs to FP16 + CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::OutputLayer>)); + + // Checks that data type is FP32 + Layer* const addLayer = GetFirstLayerWithName(graph, "add"); + + CHECK(addLayer->GetDataType() == armnn::DataType::Float32); + CHECK(addLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float32); + CHECK(addLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float32); +} + +TEST_CASE("ReduceFp32ToFp16EnabledFirstBackendHasFp16SupportTest") +{ + using namespace armnn; + + // Create a mock backend without FP16 support + MockImportBackendInitialiser initialiser; // Register the Mock Backend + auto backendObjPtr = CreateBackendObject(MockImportBackendId()); + CHECK((backendObjPtr != nullptr)); + + BackendIdSet backendIds = BackendRegistryInstance().GetBackendIds(); + if (backendIds.find("MockRef") == backendIds.end()) + { + std::string message = "Cannot load MockRef"; + FAIL(message); + } + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); + IConnectableLayer* input2 = net->AddInputLayer(2, "input2"); + IConnectableLayer* add = net->AddElementwiseBinaryLayer(BinaryOperation::Add, "add"); + IConnectableLayer* sub = net->AddElementwiseBinaryLayer(BinaryOperation::Sub, "sub"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); + input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); + input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0)); + add->GetOutputSlot(0).Connect(sub->GetInputSlot(1)); + sub->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32); + + input0->GetOutputSlot(0).SetTensorInfo(info); + input1->GetOutputSlot(0).SetTensorInfo(info); + input2->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); + sub->GetOutputSlot(0).SetTensorInfo(info); + + std::vector<BackendId> backends = { Compute::CpuRef, "MockRef" }; + + // optimize the network + OptimizerOptionsOpaque optOptions; + optOptions.SetReduceFp32ToFp16(true); + IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions); + + Graph& graph = GetGraphForTesting(optNet.get()); + + // Layers are added to convert the inputs to FP16 + CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::ConvertFp16ToFp32Layer>, + &IsLayerOfType<armnn::OutputLayer>)); + + Layer* const addLayer = GetFirstLayerWithName(graph, "add"); + Layer* const subLayer = GetFirstLayerWithName(graph, "sub"); + + CHECK(addLayer->GetDataType() == armnn::DataType::Float16); + CHECK(addLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float16); + CHECK(addLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float16); + + CHECK(subLayer->GetDataType() == armnn::DataType::Float16); + CHECK(subLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float16); + CHECK(subLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float16); +} + +TEST_CASE("ReduceFp32ToFp16EnabledFirstBackendNoFp16SupportTest") +{ + using namespace armnn; + + // Create a mock backend without FP16 support + MockImportBackendInitialiser initialiser; // Register the Mock Backend + auto backendObjPtr = CreateBackendObject(MockImportBackendId()); + CHECK((backendObjPtr != nullptr)); + + BackendIdSet backendIds = BackendRegistryInstance().GetBackendIds(); + if (backendIds.find("MockRef") == backendIds.end()) + { + std::string message = "Cannot load MockRef"; + FAIL(message); + } + + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); + IConnectableLayer* input2 = net->AddInputLayer(2, "input2"); + IConnectableLayer* add = net->AddElementwiseBinaryLayer(BinaryOperation::Add, "add"); + IConnectableLayer* sub = net->AddElementwiseBinaryLayer(BinaryOperation::Sub, "sub"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); + input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); + input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0)); + add->GetOutputSlot(0).Connect(sub->GetInputSlot(1)); + sub->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32); + + input0->GetOutputSlot(0).SetTensorInfo(info); + input1->GetOutputSlot(0).SetTensorInfo(info); + input2->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); + sub->GetOutputSlot(0).SetTensorInfo(info); + + std::vector<BackendId> backends = { "MockRef", Compute::CpuRef }; + + // optimize the network + OptimizerOptionsOpaque optOptions; + optOptions.SetReduceFp32ToFp16(true); + IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions); + + Graph& graph = GetGraphForTesting(optNet.get()); + + // Do not add layers to convert the inputs to FP16 + CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::ElementwiseBinaryLayer>, + &IsLayerOfType<armnn::OutputLayer>)); + + // Checks that data type is FP32 + Layer* const addLayer = GetFirstLayerWithName(graph, "add"); + Layer* const subLayer = GetFirstLayerWithName(graph, "sub"); + + CHECK(addLayer->GetDataType() == armnn::DataType::Float32); + CHECK(addLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float32); + CHECK(addLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float32); + + CHECK(subLayer->GetDataType() == armnn::DataType::Float32); + CHECK(subLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType() + == armnn::DataType::Float32); + CHECK(subLayer->GetOutputSlot(0).GetTensorInfo().GetDataType() == armnn::DataType::Float32); +} +#endif // ARMNNREF_ENABLED + }
\ No newline at end of file |