1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "DriverTestHelpers.hpp"
6
7 #include "../1.0/HalPolicy.hpp"
8
9 #include <boost/test/unit_test.hpp>
10
11 #include <log/log.h>
12
13 BOOST_AUTO_TEST_SUITE(ConcurrentDriverTests)
14
15 using ArmnnDriver = armnn_driver::ArmnnDriver;
16 using DriverOptions = armnn_driver::DriverOptions;
17 using HalPolicy = armnn_driver::hal_1_0::HalPolicy;
18
19 using namespace android::nn;
20 using namespace android::hardware;
21 using namespace driverTestHelpers;
22 using namespace armnn_driver;
23
24 // Add our own test for concurrent execution
25 // The main point of this test is to check that multiple requests can be
26 // executed without waiting for the callback from previous execution.
27 // The operations performed are not significant.
BOOST_AUTO_TEST_CASE(ConcurrentExecute)28 BOOST_AUTO_TEST_CASE(ConcurrentExecute)
29 {
30 ALOGI("ConcurrentExecute: entry");
31
32 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
33 HalPolicy::Model model = {};
34
35 // add operands
36 int32_t actValue = 0;
37 float weightValue[] = {2, 4, 1};
38 float biasValue[] = {4};
39
40 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
41 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3}, weightValue);
42 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1}, biasValue);
43 AddIntOperand<HalPolicy>(model, actValue);
44 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
45
46 // make the fully connected operation
47 model.operations.resize(1);
48 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
49 model.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
50 model.operations[0].outputs = hidl_vec<uint32_t>{4};
51
52 // make the prepared models
53 const size_t maxRequests = 5;
54 size_t preparedModelsSize = 0;
55 android::sp<V1_0::IPreparedModel> preparedModels[maxRequests];
56 for (size_t i = 0; i < maxRequests; ++i)
57 {
58 auto preparedModel = PrepareModel(model, *driver);
59 if (preparedModel.get() != nullptr)
60 {
61 preparedModels[i] = PrepareModel(model, *driver);
62 preparedModelsSize++;
63 }
64 }
65
66 BOOST_TEST(maxRequests == preparedModelsSize);
67
68 // construct the request data
69 DataLocation inloc = {};
70 inloc.poolIndex = 0;
71 inloc.offset = 0;
72 inloc.length = 3 * sizeof(float);
73 RequestArgument input = {};
74 input.location = inloc;
75 input.dimensions = hidl_vec<uint32_t>{};
76
77 DataLocation outloc = {};
78 outloc.poolIndex = 1;
79 outloc.offset = 0;
80 outloc.length = 1 * sizeof(float);
81 RequestArgument output = {};
82 output.location = outloc;
83 output.dimensions = hidl_vec<uint32_t>{};
84
85 // build the requests
86 V1_0::Request requests[maxRequests];
87 android::sp<IMemory> outMemory[maxRequests];
88 float* outdata[maxRequests];
89 for (size_t i = 0; i < maxRequests; ++i)
90 {
91 requests[i].inputs = hidl_vec<RequestArgument>{input};
92 requests[i].outputs = hidl_vec<RequestArgument>{output};
93 // set the input data (matching source test)
94 float indata[] = {2, 32, 16};
95 AddPoolAndSetData<float>(3, requests[i], indata);
96 // add memory for the output
97 outMemory[i] = AddPoolAndGetData<float>(1, requests[i]);
98 outdata[i] = static_cast<float*>(static_cast<void*>(outMemory[i]->getPointer()));
99 }
100
101 // invoke the execution of the requests
102 ALOGI("ConcurrentExecute: executing requests");
103 android::sp<ExecutionCallback> cb[maxRequests];
104 for (size_t i = 0; i < maxRequests; ++i)
105 {
106 cb[i] = ExecuteNoWait(preparedModels[i], requests[i]);
107 }
108
109 // wait for the requests to complete
110 ALOGI("ConcurrentExecute: waiting for callbacks");
111 for (size_t i = 0; i < maxRequests; ++i)
112 {
113 ARMNN_ASSERT(cb[i]);
114 cb[i]->wait();
115 }
116
117 // check the results
118 ALOGI("ConcurrentExecute: validating results");
119 for (size_t i = 0; i < maxRequests; ++i)
120 {
121 BOOST_TEST(outdata[i][0] == 152);
122 }
123 ALOGI("ConcurrentExecute: exit");
124 }
125
126 BOOST_AUTO_TEST_SUITE_END()
127