1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "../DriverTestHelpers.hpp"
7
8 #include <1.3/HalPolicy.hpp>
9
10 DOCTEST_TEST_SUITE("QosTests")
11 {
12 using ArmnnDriver = armnn_driver::ArmnnDriver;
13 using DriverOptions = armnn_driver::DriverOptions;
14
15 using namespace android::nn;
16 using namespace android::hardware;
17 using namespace driverTestHelpers;
18 using namespace armnn_driver;
19
20 using HalPolicy = hal_1_3::HalPolicy;
21
22 namespace
23 {
24
ExecuteModel(const armnn_driver::hal_1_3::HalPolicy::Model & model,armnn_driver::ArmnnDriver & driver,const V1_0::Request & request)25 void ExecuteModel(const armnn_driver::hal_1_3::HalPolicy::Model& model,
26 armnn_driver::ArmnnDriver& driver,
27 const V1_0::Request& request)
28 {
29 android::sp<V1_3::IPreparedModel> preparedModel = PrepareModel_1_3(model, driver);
30 if (preparedModel.get() != nullptr)
31 {
32 Execute(preparedModel, request);
33 }
34 }
35
36 DOCTEST_TEST_CASE("ConcurrentExecuteWithQosPriority")
37 {
38 ALOGI("ConcurrentExecuteWithQOSPriority: entry");
39
40 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
41 HalPolicy::Model model = {};
42
43 // add operands
44 int32_t actValue = 0;
45 float weightValue[] = {2, 4, 1};
46 float biasValue[] = {4};
47
48 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
49 AddTensorOperand<HalPolicy>(model,
50 hidl_vec<uint32_t>{1, 3},
51 weightValue,
52 HalPolicy::OperandType::TENSOR_FLOAT32,
53 V1_3::OperandLifeTime::CONSTANT_COPY);
54 AddTensorOperand<HalPolicy>(model,
55 hidl_vec<uint32_t>{1},
56 biasValue,
57 HalPolicy::OperandType::TENSOR_FLOAT32,
58 V1_3::OperandLifeTime::CONSTANT_COPY);
59 AddIntOperand<HalPolicy>(model, actValue);
60 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
61
62 // make the fully connected operation
63 model.main.operations.resize(1);
64 model.main.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
65 model.main.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
66 model.main.operations[0].outputs = hidl_vec<uint32_t>{4};
67
68 // make the prepared models
69 const size_t maxRequests = 45;
70 size_t preparedModelsSize = 0;
71 android::sp<V1_3::IPreparedModel> preparedModels[maxRequests];
72 V1_3::ErrorStatus status(V1_3::ErrorStatus::NONE);
73 size_t start = preparedModelsSize;
74 for (size_t i = start; i < start+15; ++i)
75 {
76 preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::LOW);
77 preparedModelsSize++;
78 }
79 start = preparedModelsSize;
80 for (size_t i = start; i < start+15; ++i)
81 {
82 preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::MEDIUM);
83 preparedModelsSize++;
84 }
85 start = preparedModelsSize;
86 for (size_t i = start; i < start+15; ++i)
87 {
88 preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::HIGH);
89 preparedModelsSize++;
90 }
91
92 DOCTEST_CHECK(maxRequests == preparedModelsSize);
93
94 // construct the request data
95 V1_0::DataLocation inloc = {};
96 inloc.poolIndex = 0;
97 inloc.offset = 0;
98 inloc.length = 3 * sizeof(float);
99 RequestArgument input = {};
100 input.location = inloc;
101 input.dimensions = hidl_vec<uint32_t>{};
102
103 V1_0::DataLocation outloc = {};
104 outloc.poolIndex = 1;
105 outloc.offset = 0;
106 outloc.length = 1 * sizeof(float);
107 RequestArgument output = {};
108 output.location = outloc;
109 output.dimensions = hidl_vec<uint32_t>{};
110
111 // build the requests
112 V1_0::Request requests[maxRequests];
113 android::sp<IMemory> outMemory[maxRequests];
114 float* outdata[maxRequests];
115 for (size_t i = 0; i < maxRequests; ++i)
116 {
117 requests[i].inputs = hidl_vec<RequestArgument>{input};
118 requests[i].outputs = hidl_vec<RequestArgument>{output};
119 // set the input data (matching source test)
120 float inDataLow[] = {2, 32, 16};
121 float inDataMedium[] = {1, 31, 11};
122 float inDataHigh[] = {3, 33, 17};
123 if (i < 15)
124 {
125 AddPoolAndSetData<float>(3, requests[i], inDataLow);
126 }
127 else if (i < 30)
128 {
129 AddPoolAndSetData<float>(3, requests[i], inDataMedium);
130 }
131 else
132 {
133 AddPoolAndSetData<float>(3, requests[i], inDataHigh);
134 }
135 // add memory for the output
136 outMemory[i] = AddPoolAndGetData<float>(1, requests[i]);
137 outdata[i] = static_cast<float*>(static_cast<void*>(outMemory[i]->getPointer()));
138 }
139
140 // invoke the execution of the requests
141 ALOGI("ConcurrentExecuteWithQOSPriority: executing requests");
142 android::sp<ExecutionCallback> cb[maxRequests];
143 for (size_t i = 0; i < maxRequests; ++i)
144 {
145 cb[i] = ExecuteNoWait(preparedModels[i], requests[i]);
146 }
147
148 // wait for the requests to complete
149 ALOGI("ConcurrentExecuteWithQOSPriority: waiting for callbacks");
150 for (size_t i = 0; i < maxRequests; ++i)
151 {
152 DOCTEST_CHECK(cb[i]);
153 cb[i]->wait();
154 }
155
156 // check the results
157 ALOGI("ConcurrentExecuteWithQOSPriority: validating results");
158 for (size_t i = 0; i < maxRequests; ++i)
159 {
160 if (i < 15)
161 {
162 DOCTEST_CHECK(outdata[i][0] == 152);
163 }
164 else if (i < 30)
165 {
166 DOCTEST_CHECK(outdata[i][0] == 141);
167 }
168 else
169 {
170 DOCTEST_CHECK(outdata[i][0] == 159);
171 }
172
173 }
174 ALOGI("ConcurrentExecuteWithQOSPriority: exit");
175 }
176
177 } // anonymous namespace
178
179 }