xref: /aosp_15_r20/external/armnn/src/backends/reference/test/RefOptimizedNetworkTests.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
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