1 // 2 // Copyright © 2017, 2023 Arm Ltd. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include "NeonWorkloadFactoryHelper.hpp" 7 8 #include <Graph.hpp> 9 #include <Network.hpp> 10 11 #include <neon/NeonWorkloadFactory.hpp> 12 13 #include <doctest/doctest.h> 14 15 TEST_SUITE("NeonOptimizedNetwork") 16 { 17 TEST_CASE("OptimizeValidateCpuAccDeviceSupportLayerNoFallback") 18 { 19 // build up the structure of the network 20 armnn::INetworkPtr net(armnn::INetwork::Create()); 21 22 armnn::IConnectableLayer* input = net->AddInputLayer(0); 23 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 24 25 input->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 26 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 27 28 armnn::IRuntime::CreationOptions options; 29 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 30 31 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc }; 32 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); 33 CHECK(optNet); 34 // validate workloads 35 armnn::NeonWorkloadFactory fact = 36 NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager()); 37 38 armnn::Graph& graph = GetGraphForTesting(optNet.get()); 39 for (auto&& layer : graph) 40 { 41 CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc); 42 CHECK_NOTHROW( 43 layer->CreateWorkload(fact)); 44 } 45 } 46 47 TEST_CASE("OptimizeValidateDeviceNonSupportLayerNoFallback") 48 { 49 // build up the structure of the network 50 armnn::INetworkPtr net(armnn::INetwork::Create()); 51 52 armnn::IConnectableLayer* input = net->AddInputLayer(0); 53 54 // This layer configuration isn't supported by CpuAcc and isn't allowed to fall back, so Optimize will return null. 55 armnn::NormalizationDescriptor descriptor; 56 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor); 57 58 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 59 60 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0)); 61 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 62 63 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 64 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 65 66 armnn::IRuntime::CreationOptions options; 67 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 68 69 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc }; 70 std::vector<std::string> errMessages; 71 72 try 73 { 74 Optimize(*net, backends, runtime->GetDeviceSpec(), 75 armnn::OptimizerOptionsOpaque(), errMessages); 76 FAIL("Should have thrown an exception."); 77 } 78 catch (const armnn::InvalidArgumentException& e) 79 { 80 // Different exceptions are thrown on different backends 81 } 82 CHECK(errMessages.size() > 0); 83 } 84 85 TEST_CASE("FastMathEnabledTestOnCpuAcc") 86 { 87 armnn::INetworkPtr net(armnn::INetwork::Create()); 88 89 armnn::IConnectableLayer* input = net->AddInputLayer(0); 90 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 91 92 input->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 93 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 94 95 armnn::IRuntime::CreationOptions options; 96 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 97 98 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuAcc}; 99 armnn::OptimizerOptionsOpaque optimizerOptions; 100 armnn::BackendOptions modelOptions("CpuAcc", {{"FastMathEnabled", true}}); 101 optimizerOptions.AddModelOption(modelOptions); 102 103 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize( 104 *net, backends, runtime->GetDeviceSpec(), optimizerOptions); 105 106 CHECK(optimizedNet); 107 108 auto modelOptionsOut = GetModelOptionsForTesting(optimizedNet.get()); 109 110 CHECK(modelOptionsOut.size() == 2); // FastMathEnabled and the Global to hold the import export values. 111 CHECK(modelOptionsOut[0].GetOption(0).GetName() == "FastMathEnabled"); 112 CHECK(modelOptionsOut[0].GetOption(0).GetValue().AsBool() == true); 113 } 114 115 TEST_CASE("NumberOfThreadsTestOnCpuAcc") 116 { 117 armnn::INetworkPtr net(armnn::INetwork::Create()); 118 119 armnn::IConnectableLayer* input = net->AddInputLayer(0); 120 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 121 122 input->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 123 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 124 125 armnn::IRuntime::CreationOptions options; 126 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 127 128 unsigned int numberOfThreads = 2; 129 130 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuAcc}; 131 armnn::OptimizerOptionsOpaque optimizerOptions; 132 armnn::BackendOptions modelOptions("CpuAcc", {{"NumberOfThreads", numberOfThreads}}); 133 optimizerOptions.AddModelOption(modelOptions); 134 135 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize( 136 *net, backends, runtime->GetDeviceSpec(), optimizerOptions); 137 138 CHECK(optimizedNet); 139 std::unique_ptr<armnn::Graph> graphPtr; 140 armnn::OptimizedNetworkImpl impl(std::move(graphPtr), optimizerOptions.GetModelOptions()); 141 142 auto modelOptionsOut = impl.GetModelOptions(); 143 144 CHECK(modelOptionsOut.size() == 1); 145 CHECK(modelOptionsOut[0].GetOption(0).GetName() == "NumberOfThreads"); 146 CHECK(modelOptionsOut[0].GetOption(0).GetValue().AsUnsignedInt() == numberOfThreads); 147 } 148 149 }