1*3e777be0SXin Li //
2*3e777be0SXin Li // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3*3e777be0SXin Li // SPDX-License-Identifier: MIT
4*3e777be0SXin Li //
5*3e777be0SXin Li
6*3e777be0SXin Li #include "../DriverTestHelpers.hpp"
7*3e777be0SXin Li #include "../TestHalfTensor.hpp"
8*3e777be0SXin Li
9*3e777be0SXin Li #include <1.2/HalPolicy.hpp>
10*3e777be0SXin Li
11*3e777be0SXin Li #include <array>
12*3e777be0SXin Li
13*3e777be0SXin Li using Half = half_float::half;
14*3e777be0SXin Li
15*3e777be0SXin Li using namespace android::hardware;
16*3e777be0SXin Li using namespace driverTestHelpers;
17*3e777be0SXin Li using namespace armnn_driver;
18*3e777be0SXin Li
19*3e777be0SXin Li using HalPolicy = hal_1_2::HalPolicy;
20*3e777be0SXin Li using RequestArgument = V1_0::RequestArgument;
21*3e777be0SXin Li
22*3e777be0SXin Li namespace
23*3e777be0SXin Li {
24*3e777be0SXin Li
MeanTestImpl(const TestHalfTensor & input,const hidl_vec<uint32_t> & axisDimensions,const int32_t * axisValues,int32_t keepDims,const TestHalfTensor & expectedOutput,bool fp16Enabled,armnn::Compute computeDevice)25*3e777be0SXin Li void MeanTestImpl(const TestHalfTensor& input,
26*3e777be0SXin Li const hidl_vec<uint32_t>& axisDimensions,
27*3e777be0SXin Li const int32_t* axisValues,
28*3e777be0SXin Li int32_t keepDims,
29*3e777be0SXin Li const TestHalfTensor& expectedOutput,
30*3e777be0SXin Li bool fp16Enabled,
31*3e777be0SXin Li armnn::Compute computeDevice)
32*3e777be0SXin Li {
33*3e777be0SXin Li auto driver = std::make_unique<ArmnnDriver>(DriverOptions(computeDevice, fp16Enabled));
34*3e777be0SXin Li
35*3e777be0SXin Li HalPolicy::Model model = {};
36*3e777be0SXin Li
37*3e777be0SXin Li AddInputOperand<HalPolicy>(model, input.GetDimensions(), V1_2::OperandType::TENSOR_FLOAT16);
38*3e777be0SXin Li
39*3e777be0SXin Li AddTensorOperand<HalPolicy>(model,
40*3e777be0SXin Li axisDimensions,
41*3e777be0SXin Li const_cast<int32_t*>(axisValues),
42*3e777be0SXin Li HalPolicy::OperandType::TENSOR_INT32);
43*3e777be0SXin Li
44*3e777be0SXin Li AddIntOperand<HalPolicy>(model, keepDims);
45*3e777be0SXin Li
46*3e777be0SXin Li AddOutputOperand<HalPolicy>(model, expectedOutput.GetDimensions(), V1_2::OperandType::TENSOR_FLOAT16);
47*3e777be0SXin Li
48*3e777be0SXin Li model.operations.resize(1);
49*3e777be0SXin Li model.operations[0].type = HalPolicy::OperationType::MEAN;
50*3e777be0SXin Li model.operations[0].inputs = hidl_vec<uint32_t>{ 0, 1, 2 };
51*3e777be0SXin Li model.operations[0].outputs = hidl_vec<uint32_t>{ 3 };
52*3e777be0SXin Li model.relaxComputationFloat32toFloat16 = fp16Enabled;
53*3e777be0SXin Li
54*3e777be0SXin Li //android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
55*3e777be0SXin Li android::sp<V1_2::IPreparedModel> preparedModel = PrepareModel_1_2(model, *driver);
56*3e777be0SXin Li
57*3e777be0SXin Li // The request's memory pools will follow the same order as the inputs
58*3e777be0SXin Li V1_0::DataLocation inLoc = {};
59*3e777be0SXin Li inLoc.poolIndex = 0;
60*3e777be0SXin Li inLoc.offset = 0;
61*3e777be0SXin Li inLoc.length = input.GetNumElements() * sizeof(Half);
62*3e777be0SXin Li RequestArgument inArg = {};
63*3e777be0SXin Li inArg.location = inLoc;
64*3e777be0SXin Li inArg.dimensions = input.GetDimensions();
65*3e777be0SXin Li
66*3e777be0SXin Li // An additional memory pool is needed for the output
67*3e777be0SXin Li V1_0::DataLocation outLoc = {};
68*3e777be0SXin Li outLoc.poolIndex = 1;
69*3e777be0SXin Li outLoc.offset = 0;
70*3e777be0SXin Li outLoc.length = expectedOutput.GetNumElements() * sizeof(Half);
71*3e777be0SXin Li RequestArgument outArg = {};
72*3e777be0SXin Li outArg.location = outLoc;
73*3e777be0SXin Li outArg.dimensions = expectedOutput.GetDimensions();
74*3e777be0SXin Li
75*3e777be0SXin Li // Make the request based on the arguments
76*3e777be0SXin Li V1_0::Request request = {};
77*3e777be0SXin Li request.inputs = hidl_vec<RequestArgument>{ inArg };
78*3e777be0SXin Li request.outputs = hidl_vec<RequestArgument>{ outArg };
79*3e777be0SXin Li
80*3e777be0SXin Li // Set the input data
81*3e777be0SXin Li AddPoolAndSetData(input.GetNumElements(), request, input.GetData());
82*3e777be0SXin Li
83*3e777be0SXin Li // Add memory for the output
84*3e777be0SXin Li android::sp<IMemory> outMemory = AddPoolAndGetData<Half>(expectedOutput.GetNumElements(), request);
85*3e777be0SXin Li const Half* outputData = static_cast<const Half*>(static_cast<void*>(outMemory->getPointer()));
86*3e777be0SXin Li
87*3e777be0SXin Li if (preparedModel.get() != nullptr)
88*3e777be0SXin Li {
89*3e777be0SXin Li V1_0::ErrorStatus execStatus = Execute(preparedModel, request);
90*3e777be0SXin Li DOCTEST_CHECK((int)execStatus == (int)V1_0::ErrorStatus::NONE);
91*3e777be0SXin Li }
92*3e777be0SXin Li
93*3e777be0SXin Li const Half* expectedOutputData = expectedOutput.GetData();
94*3e777be0SXin Li for (unsigned int i = 0; i < expectedOutput.GetNumElements(); i++)
95*3e777be0SXin Li {
96*3e777be0SXin Li DOCTEST_CHECK(outputData[i] == expectedOutputData[i]);
97*3e777be0SXin Li }
98*3e777be0SXin Li }
99*3e777be0SXin Li
100*3e777be0SXin Li } // anonymous namespace
101*3e777be0SXin Li
102*3e777be0SXin Li DOCTEST_TEST_SUITE("MeanTests_1.2_CpuRef")
103*3e777be0SXin Li {
104*3e777be0SXin Li
105*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16NoKeepDimsTest_CpuRef")
106*3e777be0SXin Li {
107*3e777be0SXin Li using namespace half_float::literal;
108*3e777be0SXin Li
109*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 4, 3, 2 },
110*3e777be0SXin Li { 1.0_h, 2.0_h, 3.0_h, 4.0_h, 5.0_h, 6.0_h, 7.0_h, 8.0_h, 9.0_h, 10.0_h,
111*3e777be0SXin Li 11.0_h, 12.0_h, 13.0_h, 14.0_h, 15.0_h, 16.0_h, 17.0_h, 18.0_h, 19.0_h,
112*3e777be0SXin Li 20.0_h, 21.0_h, 22.0_h, 23.0_h, 24.0_h } };
113*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 2 };
114*3e777be0SXin Li int32_t axisValues[] = { 0, 1 };
115*3e777be0SXin Li int32_t keepDims = 0;
116*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0_h, 13.0_h } };
117*3e777be0SXin Li
118*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuRef);
119*3e777be0SXin Li }
120*3e777be0SXin Li
121*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16KeepDimsTest_CpuRef")
122*3e777be0SXin Li {
123*3e777be0SXin Li using namespace half_float::literal;
124*3e777be0SXin Li
125*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0_h, 1.0_h, 2.0_h, 2.0_h, 3.0_h, 3.0_h } };
126*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 1 };
127*3e777be0SXin Li int32_t axisValues[] = { 2 };
128*3e777be0SXin Li int32_t keepDims = 1;
129*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0_h, 2.0_h } };
130*3e777be0SXin Li
131*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuRef);
132*3e777be0SXin Li }
133*3e777be0SXin Li
134*3e777be0SXin Li }
135*3e777be0SXin Li
136*3e777be0SXin Li #ifdef ARMCOMPUTECL_ENABLED
137*3e777be0SXin Li DOCTEST_TEST_SUITE("MeanTests_1.2_CpuAcc")
138*3e777be0SXin Li {
139*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16NoKeepDimsTest_CpuAcc")
140*3e777be0SXin Li {
141*3e777be0SXin Li using namespace half_float::literal;
142*3e777be0SXin Li
143*3e777be0SXin Li std::vector<Half> in = { 1.0_h, 2.0_h, 3.0_h, 4.0_h, 5.0_h, 6.0_h, 7.0_h, 8.0_h, 9.0_h, 10.0_h,
144*3e777be0SXin Li 11.0_h, 12.0_h, 13.0_h, 14.0_h, 15.0_h, 16.0_h, 17.0_h, 18.0_h, 19.0_h,
145*3e777be0SXin Li 20.0_h, 21.0_h, 22.0_h, 23.0_h, 24.0_h };
146*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 4, 3, 2 },
147*3e777be0SXin Li in};
148*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 2 };
149*3e777be0SXin Li int32_t axisValues[] = { 0, 1 };
150*3e777be0SXin Li int32_t keepDims = 0;
151*3e777be0SXin Li std::vector<Half> out = { 12.0_h, 13.0_h };
152*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 2 }, out };
153*3e777be0SXin Li
154*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuAcc);
155*3e777be0SXin Li }
156*3e777be0SXin Li
157*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16KeepDimsTest_CpuAcc")
158*3e777be0SXin Li {
159*3e777be0SXin Li using namespace half_float::literal;
160*3e777be0SXin Li
161*3e777be0SXin Li std::vector<Half> in = { 1.0_h, 1.0_h, 2.0_h, 2.0_h, 3.0_h, 3.0_h };
162*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, in };
163*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 1 };
164*3e777be0SXin Li int32_t axisValues[] = { 2 };
165*3e777be0SXin Li int32_t keepDims = 1;
166*3e777be0SXin Li std::vector<Half> out = { 2.0_h, 2.0_h };
167*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, out };
168*3e777be0SXin Li
169*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::CpuAcc);
170*3e777be0SXin Li }
171*3e777be0SXin Li }
172*3e777be0SXin Li
173*3e777be0SXin Li DOCTEST_TEST_SUITE("MeanTests_1.2_GpuAcc")
174*3e777be0SXin Li {
175*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16NoKeepDimsTest_GpuAcc")
176*3e777be0SXin Li {
177*3e777be0SXin Li using namespace half_float::literal;
178*3e777be0SXin Li
179*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 4, 3, 2 },
180*3e777be0SXin Li { 1.0_h, 2.0_h, 3.0_h, 4.0_h, 5.0_h, 6.0_h, 7.0_h, 8.0_h, 9.0_h, 10.0_h,
181*3e777be0SXin Li 11.0_h, 12.0_h, 13.0_h, 14.0_h, 15.0_h, 16.0_h, 17.0_h, 18.0_h, 19.0_h,
182*3e777be0SXin Li 20.0_h, 21.0_h, 22.0_h, 23.0_h, 24.0_h } };
183*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 2 };
184*3e777be0SXin Li int32_t axisValues[] = { 0, 1 };
185*3e777be0SXin Li int32_t keepDims = 0;
186*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 2 }, { 12.0_h, 13.0_h } };
187*3e777be0SXin Li
188*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::GpuAcc);
189*3e777be0SXin Li }
190*3e777be0SXin Li
191*3e777be0SXin Li DOCTEST_TEST_CASE("MeanFp16KeepDimsTest_GpuAcc")
192*3e777be0SXin Li {
193*3e777be0SXin Li using namespace half_float::literal;
194*3e777be0SXin Li
195*3e777be0SXin Li TestHalfTensor input{ armnn::TensorShape{ 1, 1, 3, 2 }, { 1.0_h, 1.0_h, 2.0_h, 2.0_h, 3.0_h, 3.0_h } };
196*3e777be0SXin Li hidl_vec<uint32_t> axisDimensions = { 1 };
197*3e777be0SXin Li int32_t axisValues[] = { 2 };
198*3e777be0SXin Li int32_t keepDims = 1;
199*3e777be0SXin Li TestHalfTensor expectedOutput{ armnn::TensorShape{ 1, 1, 1, 2 }, { 2.0_h, 2.0_h } };
200*3e777be0SXin Li
201*3e777be0SXin Li MeanTestImpl(input, axisDimensions, axisValues, keepDims, expectedOutput, true, armnn::Compute::GpuAcc);
202*3e777be0SXin Li }
203*3e777be0SXin Li }
204*3e777be0SXin Li #endif
205