1 //
2 // Copyright © 2017, 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "../DriverTestHelpers.hpp"
7 #include "../TestTensor.hpp"
8
9 #include <1.1/HalPolicy.hpp>
10
11 #include <array>
12
13 using namespace android::hardware;
14 using namespace driverTestHelpers;
15 using namespace armnn_driver;
16
17 using HalPolicy = hal_1_1::HalPolicy;
18 using RequestArgument = V1_0::RequestArgument;
19
20 namespace
21 {
22
MeanTestImpl(const TestTensor & input,const hidl_vec<uint32_t> & axisDimensions,const int32_t * axisValues,int32_t keepDims,const TestTensor & expectedOutput,bool fp16Enabled,armnn::Compute computeDevice)23 void MeanTestImpl(const TestTensor& input,
24 const hidl_vec<uint32_t>& axisDimensions,
25 const int32_t* axisValues,
26 int32_t keepDims,
27 const TestTensor& expectedOutput,
28 bool fp16Enabled,
29 armnn::Compute computeDevice)
30 {
31 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(computeDevice, fp16Enabled));
32
33 HalPolicy::Model model = {};
34
35 AddInputOperand<HalPolicy>(model, input.GetDimensions());
36
37 AddTensorOperand<HalPolicy>(model,
38 axisDimensions,
39 const_cast<int32_t*>(axisValues),
40 HalPolicy::OperandType::TENSOR_INT32);
41
42 AddIntOperand<HalPolicy>(model, keepDims);
43
44 AddOutputOperand<HalPolicy>(model, expectedOutput.GetDimensions());
45
46 model.operations.resize(1);
47 model.operations[0].type = HalPolicy::OperationType::MEAN;
48 model.operations[0].inputs = hidl_vec<uint32_t>{ 0, 1, 2 };
49 model.operations[0].outputs = hidl_vec<uint32_t>{ 3 };
50 model.relaxComputationFloat32toFloat16 = fp16Enabled;
51
52 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
53
54 // The request's memory pools will follow the same order as the inputs
55 V1_0::DataLocation inLoc = {};
56 inLoc.poolIndex = 0;
57 inLoc.offset = 0;
58 inLoc.length = input.GetNumElements() * sizeof(float);
59 RequestArgument inArg = {};
60 inArg.location = inLoc;
61 inArg.dimensions = input.GetDimensions();
62
63 // An additional memory pool is needed for the output
64 V1_0::DataLocation outLoc = {};
65 outLoc.poolIndex = 1;
66 outLoc.offset = 0;
67 outLoc.length = expectedOutput.GetNumElements() * sizeof(float);
68 RequestArgument outArg = {};
69 outArg.location = outLoc;
70 outArg.dimensions = expectedOutput.GetDimensions();
71
72 // Make the request based on the arguments
73 V1_0::Request request = {};
74 request.inputs = hidl_vec<RequestArgument>{ inArg };
75 request.outputs = hidl_vec<RequestArgument>{ outArg };
76
77 // Set the input data
78 AddPoolAndSetData(input.GetNumElements(), request, input.GetData());
79
80 // Add memory for the output
81 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(expectedOutput.GetNumElements(), request);
82 const float* outputData = static_cast<const float*>(static_cast<void*>(outMemory->getPointer()));
83
84 if (preparedModel.get() != nullptr)
85 {
86 V1_0::ErrorStatus execStatus = Execute(preparedModel, request);
87 DOCTEST_CHECK((int)execStatus == (int)V1_0::ErrorStatus::NONE);
88 }
89
90 const float* expectedOutputData = expectedOutput.GetData();
91 for (unsigned int i = 0; i < expectedOutput.GetNumElements(); i++)
92 {
93 DOCTEST_CHECK(outputData[i] == expectedOutputData[i]);
94 }
95 }
96
97 } // anonymous namespace
98
99 DOCTEST_TEST_SUITE("MeanTests_CpuRef")
100 {
101
102 DOCTEST_TEST_CASE("MeanNoKeepDimsTest_CpuRef")
103 {
104 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
105 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
106 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
107 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
108 hidl_vec<uint32_t> axisDimensions = { 2 };
109 int32_t axisValues[] = { 0, 1 };
110 int32_t keepDims = 0;
111 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
112
113 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::CpuRef);
114 }
115
116 DOCTEST_TEST_CASE("MeanKeepDimsTest_CpuRef")
117 {
118 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
119 hidl_vec<uint32_t> axisDimensions = { 1 };
120 int32_t axisValues[] = { 2 };
121 int32_t keepDims = 1;
122 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
123
124 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::CpuRef);
125 }
126
127 DOCTEST_TEST_CASE("MeanFp16EnabledNoKeepDimsTest_CpuRef")
128 {
129 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
130 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
131 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
132 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
133 hidl_vec<uint32_t> axisDimensions = { 2 };
134 int32_t axisValues[] = { 0, 1 };
135 int32_t keepDims = 0;
136 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
137
138 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuRef);
139 }
140
141 DOCTEST_TEST_CASE("MeanFp16EnabledKeepDimsTest_CpuRef")
142 {
143 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
144 hidl_vec<uint32_t> axisDimensions = { 1 };
145 int32_t axisValues[] = { 2 };
146 int32_t keepDims = 1;
147 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
148
149 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuRef);
150 }
151
152 }
153
154 #ifdef ARMCOMPUTECL_ENABLED
155 DOCTEST_TEST_SUITE("MeanTests_CpuAcc")
156 {
157 DOCTEST_TEST_CASE("MeanNoKeepDimsTest_CpuAcc")
158 {
159 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
160 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
161 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
162 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
163 hidl_vec<uint32_t> axisDimensions = { 2 };
164 int32_t axisValues[] = { 0, 1 };
165 int32_t keepDims = 0;
166 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
167
168 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::CpuAcc);
169 }
170
171 DOCTEST_TEST_CASE("MeanKeepDimsTest_CpuAcc")
172 {
173 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
174 hidl_vec<uint32_t> axisDimensions = { 1 };
175 int32_t axisValues[] = { 2 };
176 int32_t keepDims = 1;
177 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
178
179 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::CpuAcc);
180 }
181
182 DOCTEST_TEST_CASE("MeanFp16EnabledNoKeepDimsTest_CpuAcc")
183 {
184 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
185 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
186 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
187 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
188 hidl_vec<uint32_t> axisDimensions = { 2 };
189 int32_t axisValues[] = { 0, 1 };
190 int32_t keepDims = 0;
191 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
192
193 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuAcc);
194 }
195
196 DOCTEST_TEST_CASE("MeanFp16EnabledKeepDimsTest_CpuAcc")
197 {
198 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
199 hidl_vec<uint32_t> axisDimensions = { 1 };
200 int32_t axisValues[] = { 2 };
201 int32_t keepDims = 1;
202 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
203
204 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuAcc);
205 }
206 }
207
208 DOCTEST_TEST_SUITE("MeanTests_GpuAcc")
209 {
210 DOCTEST_TEST_CASE("MeanNoKeepDimsTest_GpuAcc")
211 {
212 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
213 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
214 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
215 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
216 hidl_vec<uint32_t> axisDimensions = { 2 };
217 int32_t axisValues[] = { 0, 1 };
218 int32_t keepDims = 0;
219 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
220
221 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::GpuAcc);
222 }
223
224 DOCTEST_TEST_CASE("MeanKeepDimsTest_GpuAcc")
225 {
226 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
227 hidl_vec<uint32_t> axisDimensions = { 1 };
228 int32_t axisValues[] = { 2 };
229 int32_t keepDims = 1;
230 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
231
232 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, false, armnn::Compute::GpuAcc);
233 }
234
235 DOCTEST_TEST_CASE("MeanFp16EnabledNoKeepDimsTest_GpuAcc")
236 {
237 TestTensor input{ armnn::TensorShape{ 4, 3, 2 },
238 { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
239 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f,
240 20.0f, 21.0f, 22.0f, 23.0f, 24.0f } };
241 hidl_vec<uint32_t> axisDimensions = { 2 };
242 int32_t axisValues[] = { 0, 1 };
243 int32_t keepDims = 0;
244 TestTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0f, 13.0f } };
245
246 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::GpuAcc);
247 }
248
249 DOCTEST_TEST_CASE("MeanFp16EnabledKeepDimsTest_GpuAcc")
250 {
251 TestTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f } };
252 hidl_vec<uint32_t> axisDimensions = { 1 };
253 int32_t axisValues[] = { 2 };
254 int32_t keepDims = 1;
255 TestTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0f, 2.0f } };
256
257 MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::GpuAcc);
258 }
259 }
260 #endif
261