1 // 2 // Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include <doctest/doctest.h> 7 #include <Graph.hpp> 8 #include <armnn/BackendId.hpp> 9 #include <armnn/Descriptors.hpp> 10 #include <armnn/INetwork.hpp> 11 #include <armnn/IRuntime.hpp> 12 #include <armnn/Tensor.hpp> 13 #include <armnn/Types.hpp> 14 #include <GraphUtils.hpp> 15 #include <reference/RefWorkloadFactory.hpp> 16 #include <memory> 17 #include <vector> 18 19 TEST_SUITE("RefOptimizedNetwork") 20 { 21 TEST_CASE("OptimizeValidateCpuRefWorkloads") 22 { 23 const armnn::TensorInfo desc({3, 5}, armnn::DataType::Float32); 24 25 // build up the structure of the network 26 armnn::INetworkPtr net(armnn::INetwork::Create()); 27 28 armnn::NormalizationDescriptor nmDesc; 29 armnn::ActivationDescriptor acDesc; 30 31 // in 32 // | 33 // nm 34 // / | 35 // ac | 36 // \ | 37 // ml 38 // | 39 // sm 40 // | 41 // ot 42 armnn::IConnectableLayer* layer = net->AddInputLayer(0, "in"); 43 layer->GetOutputSlot(0).SetTensorInfo(desc); 44 45 armnn::IConnectableLayer* const normLayer = net->AddNormalizationLayer(nmDesc, "nm"); 46 47 layer->GetOutputSlot(0).Connect(normLayer->GetInputSlot(0)); 48 normLayer->GetOutputSlot(0).SetTensorInfo(desc); 49 50 layer = net->AddActivationLayer(acDesc, "ac"); 51 52 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0)); 53 layer->GetOutputSlot(0).SetTensorInfo(desc); 54 55 armnn::IConnectableLayer* prevLayer = layer; 56 layer = net->AddElementwiseBinaryLayer(armnn::BinaryOperation::Mul, "ml"); 57 58 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0)); 59 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1)); 60 layer->GetOutputSlot(0).SetTensorInfo(desc); 61 62 prevLayer = layer; 63 armnn::SoftmaxDescriptor softmaxDescriptor; 64 layer = net->AddSoftmaxLayer(softmaxDescriptor, "sm"); 65 66 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0)); 67 layer->GetOutputSlot(0).SetTensorInfo(desc); 68 69 prevLayer = layer; 70 layer = net->AddOutputLayer(0, "ot"); 71 72 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0)); 73 74 armnn::IRuntime::CreationOptions options; 75 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 76 77 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef }; 78 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); 79 armnn::Graph& graph = GetGraphForTesting(optNet.get()); 80 graph.AllocateDynamicBuffers(); 81 CHECK(optNet); 82 83 // Validates workloads. 84 armnn::RefWorkloadFactory fact; 85 for (auto&& layer : graph) 86 { 87 CHECK_NOTHROW(layer->CreateWorkload(fact)); 88 } 89 } 90 91 TEST_CASE("OptimizeValidateWorkloadsCpuRefPermuteLayer") 92 { 93 // Create runtime in which test will run 94 armnn::IRuntime::CreationOptions options; 95 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 96 97 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef}; 98 99 // build up the structure of the network 100 armnn::INetworkPtr net(armnn::INetwork::Create()); 101 102 armnn::IConnectableLayer* input = net->AddInputLayer(0); 103 104 armnn::PermuteDescriptor descriptor({0, 2, 3, 1}); 105 armnn::IConnectableLayer* permute = net->AddPermuteLayer(descriptor); 106 107 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 108 109 input->GetOutputSlot(0).Connect(permute->GetInputSlot(0)); 110 permute->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 111 112 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32)); 113 permute->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 4, 1, 4 }, armnn::DataType::Float32)); 114 115 // optimize the network 116 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); 117 118 armnn::Graph& graph = GetGraphForTesting(optNet.get()); 119 graph.AllocateDynamicBuffers(); 120 121 for (auto&& layer : graph) 122 { 123 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef); 124 } 125 } 126 127 TEST_CASE("OptimizeValidateWorkloadsCpuRefMeanLayer") 128 { 129 // Create runtime in which test will run 130 armnn::IRuntime::CreationOptions options; 131 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 132 133 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef}; 134 135 // build up the structure of the network 136 armnn::INetworkPtr net(armnn::INetwork::Create()); 137 138 armnn::IConnectableLayer* input = net->AddInputLayer(0); 139 140 armnn::MeanDescriptor descriptor({ 0, 1 }, false); 141 armnn::IConnectableLayer* meanLayer = net->AddMeanLayer(descriptor); 142 143 armnn::IConnectableLayer* output = net->AddOutputLayer(0); 144 145 input->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0)); 146 meanLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 147 148 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 4, 3, 2 }, armnn::DataType::Float32)); 149 meanLayer->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 2 }, armnn::DataType::Float32)); 150 151 // optimize the network 152 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec()); 153 armnn::Graph& graph = GetGraphForTesting(optNet.get()); 154 graph.AllocateDynamicBuffers(); 155 for (auto&& layer : graph) 156 { 157 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef); 158 } 159 } 160 161 TEST_CASE("DebugTestOnCpuRef") 162 { 163 // build up the structure of the network 164 armnn::INetworkPtr net(armnn::INetwork::Create()); 165 166 armnn::ActivationDescriptor activation1Descriptor; 167 activation1Descriptor.m_Function = armnn::ActivationFunction::BoundedReLu; 168 activation1Descriptor.m_A = 1.f; 169 activation1Descriptor.m_B = -1.f; 170 171 // Defines layers. 172 auto input = net->AddInputLayer(0, "InputLayer"); 173 auto activation = net->AddActivationLayer(activation1Descriptor, "ActivationLayer"); 174 auto output = net->AddOutputLayer(0, "OutputLayer"); 175 176 // Connects layers. 177 input->GetOutputSlot(0).Connect(activation->GetInputSlot(0)); 178 activation->GetOutputSlot(0).Connect(output->GetInputSlot(0)); 179 180 armnn::TensorShape shape({4}); 181 armnn::TensorInfo info(shape, armnn::DataType::Float32); 182 input->GetOutputSlot(0).SetTensorInfo(info); 183 activation->GetOutputSlot(0).SetTensorInfo(info); 184 185 armnn::IRuntime::CreationOptions options; 186 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); 187 188 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef}; 189 190 armnn::OptimizerOptionsOpaque optimizerOptions; 191 optimizerOptions.SetDebugEnabled(true); 192 193 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec(), 194 optimizerOptions); 195 196 armnn::Graph& graph = GetGraphForTesting(optimizedNet.get()); 197 graph.AllocateDynamicBuffers(); 198 199 // Tests that all layers are present in the graph. 200 CHECK(graph.GetNumLayers() == 5); 201 202 // Tests that the vertices exist and have correct names. 203 CHECK(GraphHasNamedLayer(graph, "InputLayer")); 204 CHECK(GraphHasNamedLayer(graph, "DebugLayerAfterInputLayer_0")); 205 CHECK(GraphHasNamedLayer(graph, "ActivationLayer")); 206 CHECK(GraphHasNamedLayer(graph, "DebugLayerAfterActivationLayer_0")); 207 CHECK(GraphHasNamedLayer(graph, "OutputLayer")); 208 } 209 210 } 211