blob: 6ab63ff2de293decc1e80c1d11fdc5c2820a35b6 [file] [log] [blame]
surmeh0149b9e102018-05-17 14:11:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
surmeh0149b9e102018-05-17 14:11:25 +01004//
5#include "DriverTestHelpers.hpp"
6#include <boost/test/unit_test.hpp>
7#include <log/log.h>
8
9BOOST_AUTO_TEST_SUITE(FullyConnectedTests)
10
telsoa01ce3e84a2018-08-31 09:31:35 +010011using namespace android::hardware;
surmeh0149b9e102018-05-17 14:11:25 +010012using namespace driverTestHelpers;
telsoa01ce3e84a2018-08-31 09:31:35 +010013using namespace armnn_driver;
surmeh0149b9e102018-05-17 14:11:25 +010014
15// Add our own test here since we fail the fc tests which Google supplies (because of non-const weights)
16BOOST_AUTO_TEST_CASE(FullyConnected)
17{
18 // this should ideally replicate fully_connected_float.model.cpp
19 // but that uses slightly weird dimensions which I don't think we need to support for now
20
21 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
Nikhil Raj77605822018-09-03 11:25:56 +010022 V1_0::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +010023
24 // add operands
25 int32_t actValue = 0;
26 float weightValue[] = {2, 4, 1};
27 float biasValue[] = {4};
28
29 AddInputOperand(model, hidl_vec<uint32_t>{1, 3});
30 AddTensorOperand(model, hidl_vec<uint32_t>{1, 3}, weightValue);
31 AddTensorOperand(model, hidl_vec<uint32_t>{1}, biasValue);
32 AddIntOperand(model, actValue);
33 AddOutputOperand(model, hidl_vec<uint32_t>{1, 1});
34
35 // make the fully connected operation
36 model.operations.resize(1);
Nikhil Raj77605822018-09-03 11:25:56 +010037 model.operations[0].type = V1_0::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +010038 model.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
39 model.operations[0].outputs = hidl_vec<uint32_t>{4};
40
41 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +010042 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +010043
44 // construct the request
45 DataLocation inloc = {};
46 inloc.poolIndex = 0;
47 inloc.offset = 0;
48 inloc.length = 3 * sizeof(float);
49 RequestArgument input = {};
50 input.location = inloc;
51 input.dimensions = hidl_vec<uint32_t>{};
52
53 DataLocation outloc = {};
54 outloc.poolIndex = 1;
55 outloc.offset = 0;
56 outloc.length = 1 * sizeof(float);
57 RequestArgument output = {};
58 output.location = outloc;
59 output.dimensions = hidl_vec<uint32_t>{};
60
61 Request request = {};
62 request.inputs = hidl_vec<RequestArgument>{input};
63 request.outputs = hidl_vec<RequestArgument>{output};
64
65 // set the input data (matching source test)
66 float indata[] = {2, 32, 16};
67 AddPoolAndSetData(3, request, indata);
68
69 // add memory for the output
70 android::sp<IMemory> outMemory = AddPoolAndGetData(1, request);
71 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
72
73 // run the execution
74 Execute(preparedModel, request);
75
76 // check the result
77 BOOST_TEST(outdata[0] == 152);
78}
79
80BOOST_AUTO_TEST_CASE(TestFullyConnected4dInput)
81{
82 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
83
84 ErrorStatus error;
85 std::vector<bool> sup;
86
87 ArmnnDriver::getSupportedOperations_cb cb = [&](ErrorStatus status, const std::vector<bool>& supported)
88 {
89 error = status;
90 sup = supported;
91 };
92
Nikhil Raj77605822018-09-03 11:25:56 +010093 V1_0::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +010094
95 // operands
96 int32_t actValue = 0;
97 float weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
98 0, 1, 0, 0, 0, 0, 0, 0,
99 0, 0, 1, 0, 0, 0, 0, 0,
100 0, 0, 0, 1, 0, 0, 0, 0,
101 0, 0, 0, 0, 1, 0, 0, 0,
102 0, 0, 0, 0, 0, 1, 0, 0,
103 0, 0, 0, 0, 0, 0, 1, 0,
104 0, 0, 0, 0, 0, 0, 0, 1}; //identity
105 float biasValue[] = {0, 0, 0, 0, 0, 0, 0, 0};
106
107 // fully connected operation
108 AddInputOperand(model, hidl_vec<uint32_t>{1, 1, 1, 8});
109 AddTensorOperand(model, hidl_vec<uint32_t>{8, 8}, weightValue);
110 AddTensorOperand(model, hidl_vec<uint32_t>{8}, biasValue);
111 AddIntOperand(model, actValue);
112 AddOutputOperand(model, hidl_vec<uint32_t>{1, 8});
113
114 model.operations.resize(1);
115
Nikhil Raj77605822018-09-03 11:25:56 +0100116 model.operations[0].type = V1_0::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +0100117 model.operations[0].inputs = hidl_vec<uint32_t>{0,1,2,3};
118 model.operations[0].outputs = hidl_vec<uint32_t>{4};
119
120 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +0100121 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +0100122
123
124 // construct the request
125 DataLocation inloc = {};
126 inloc.poolIndex = 0;
127 inloc.offset = 0;
128 inloc.length = 8 * sizeof(float);
129 RequestArgument input = {};
130 input.location = inloc;
131 input.dimensions = hidl_vec<uint32_t>{};
132
133 DataLocation outloc = {};
134 outloc.poolIndex = 1;
135 outloc.offset = 0;
136 outloc.length = 8 * sizeof(float);
137 RequestArgument output = {};
138 output.location = outloc;
139 output.dimensions = hidl_vec<uint32_t>{};
140
141 Request request = {};
142 request.inputs = hidl_vec<RequestArgument>{input};
143 request.outputs = hidl_vec<RequestArgument>{output};
144
145 // set the input data
146 float indata[] = {1,2,3,4,5,6,7,8};
147 AddPoolAndSetData(8, request, indata);
148
149 // add memory for the output
150 android::sp<IMemory> outMemory = AddPoolAndGetData(8, request);
151 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
152
153 // run the execution
154 Execute(preparedModel, request);
155
156 // check the result
157 BOOST_TEST(outdata[0] == 1);
158 BOOST_TEST(outdata[1] == 2);
159 BOOST_TEST(outdata[2] == 3);
160 BOOST_TEST(outdata[3] == 4);
161 BOOST_TEST(outdata[4] == 5);
162 BOOST_TEST(outdata[5] == 6);
163 BOOST_TEST(outdata[6] == 7);
164 BOOST_TEST(outdata[7] == 8);
165}
166
167BOOST_AUTO_TEST_CASE(TestFullyConnected4dInputReshape)
168{
169 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
170
171 ErrorStatus error;
172 std::vector<bool> sup;
173
174 ArmnnDriver::getSupportedOperations_cb cb = [&](ErrorStatus status, const std::vector<bool>& supported)
175 {
176 error = status;
177 sup = supported;
178 };
179
Nikhil Raj77605822018-09-03 11:25:56 +0100180 V1_0::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +0100181
182 // operands
183 int32_t actValue = 0;
184 float weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
185 0, 1, 0, 0, 0, 0, 0, 0,
186 0, 0, 1, 0, 0, 0, 0, 0,
187 0, 0, 0, 1, 0, 0, 0, 0,
188 0, 0, 0, 0, 1, 0, 0, 0,
189 0, 0, 0, 0, 0, 1, 0, 0,
190 0, 0, 0, 0, 0, 0, 1, 0,
191 0, 0, 0, 0, 0, 0, 0, 1}; //identity
192 float biasValue[] = {0, 0, 0, 0, 0, 0, 0, 0};
193
194 // fully connected operation
195 AddInputOperand(model, hidl_vec<uint32_t>{1, 2, 2, 2});
196 AddTensorOperand(model, hidl_vec<uint32_t>{8, 8}, weightValue);
197 AddTensorOperand(model, hidl_vec<uint32_t>{8}, biasValue);
198 AddIntOperand(model, actValue);
199 AddOutputOperand(model, hidl_vec<uint32_t>{1, 8});
200
201 model.operations.resize(1);
202
Nikhil Raj77605822018-09-03 11:25:56 +0100203 model.operations[0].type = V1_0::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +0100204 model.operations[0].inputs = hidl_vec<uint32_t>{0,1,2,3};
205 model.operations[0].outputs = hidl_vec<uint32_t>{4};
206
207 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +0100208 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +0100209
210
211 // construct the request
212 DataLocation inloc = {};
213 inloc.poolIndex = 0;
214 inloc.offset = 0;
215 inloc.length = 8 * sizeof(float);
216 RequestArgument input = {};
217 input.location = inloc;
218 input.dimensions = hidl_vec<uint32_t>{};
219
220 DataLocation outloc = {};
221 outloc.poolIndex = 1;
222 outloc.offset = 0;
223 outloc.length = 8 * sizeof(float);
224 RequestArgument output = {};
225 output.location = outloc;
226 output.dimensions = hidl_vec<uint32_t>{};
227
228 Request request = {};
229 request.inputs = hidl_vec<RequestArgument>{input};
230 request.outputs = hidl_vec<RequestArgument>{output};
231
232 // set the input data
233 float indata[] = {1,2,3,4,5,6,7,8};
234 AddPoolAndSetData(8, request, indata);
235
236 // add memory for the output
237 android::sp<IMemory> outMemory = AddPoolAndGetData(8, request);
238 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
239
240 // run the execution
241 Execute(preparedModel, request);
242
243 // check the result
244 BOOST_TEST(outdata[0] == 1);
245 BOOST_TEST(outdata[1] == 2);
246 BOOST_TEST(outdata[2] == 3);
247 BOOST_TEST(outdata[3] == 4);
248 BOOST_TEST(outdata[4] == 5);
249 BOOST_TEST(outdata[5] == 6);
250 BOOST_TEST(outdata[6] == 7);
251 BOOST_TEST(outdata[7] == 8);
252}
253
254BOOST_AUTO_TEST_SUITE_END()