• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(FullyConnectedTests)
14 
15 using namespace android::hardware;
16 using namespace driverTestHelpers;
17 using namespace armnn_driver;
18 
19 using HalPolicy = hal_1_0::HalPolicy;
20 
21 // Add our own test here since we fail the fc tests which Google supplies (because of non-const weights)
BOOST_AUTO_TEST_CASE(FullyConnected)22 BOOST_AUTO_TEST_CASE(FullyConnected)
23 {
24     // this should ideally replicate fully_connected_float.model.cpp
25     // but that uses slightly weird dimensions which I don't think we need to support for now
26 
27     auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
28     HalPolicy::Model model = {};
29 
30     // add operands
31     int32_t actValue      = 0;
32     float   weightValue[] = {2, 4, 1};
33     float   biasValue[]   = {4};
34 
35     AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
36     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3}, weightValue);
37     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1}, biasValue);
38     AddIntOperand<HalPolicy>(model, actValue);
39     AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
40 
41     // make the fully connected operation
42     model.operations.resize(1);
43     model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
44     model.operations[0].inputs  = hidl_vec<uint32_t>{0, 1, 2, 3};
45     model.operations[0].outputs = hidl_vec<uint32_t>{4};
46 
47     // make the prepared model
48     android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
49 
50     // construct the request
51     DataLocation inloc = {};
52     inloc.poolIndex = 0;
53     inloc.offset    = 0;
54     inloc.length    = 3 * sizeof(float);
55     RequestArgument input = {};
56     input.location = inloc;
57     input.dimensions = hidl_vec<uint32_t>{};
58 
59     DataLocation outloc = {};
60     outloc.poolIndex = 1;
61     outloc.offset    = 0;
62     outloc.length    = 1 * sizeof(float);
63     RequestArgument output = {};
64     output.location  = outloc;
65     output.dimensions = hidl_vec<uint32_t>{};
66 
67     V1_0::Request request = {};
68     request.inputs  = hidl_vec<RequestArgument>{input};
69     request.outputs = hidl_vec<RequestArgument>{output};
70 
71     // set the input data (matching source test)
72     float indata[] = {2, 32, 16};
73     AddPoolAndSetData<float>(3, request, indata);
74 
75     // add memory for the output
76     android::sp<IMemory> outMemory = AddPoolAndGetData<float>(1, request);
77     float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
78 
79     // run the execution
80     if (preparedModel.get() != nullptr)
81     {
82         Execute(preparedModel, request);
83     }
84 
85     // check the result
86     BOOST_TEST(outdata[0] == 152);
87 }
88 
BOOST_AUTO_TEST_CASE(TestFullyConnected4dInput)89 BOOST_AUTO_TEST_CASE(TestFullyConnected4dInput)
90 {
91     auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
92 
93     V1_0::ErrorStatus error;
94     std::vector<bool> sup;
95 
96     ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
97         {
98             error = status;
99             sup = supported;
100         };
101 
102     HalPolicy::Model model = {};
103 
104     // operands
105     int32_t actValue      = 0;
106     float   weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
107                              0, 1, 0, 0, 0, 0, 0, 0,
108                              0, 0, 1, 0, 0, 0, 0, 0,
109                              0, 0, 0, 1, 0, 0, 0, 0,
110                              0, 0, 0, 0, 1, 0, 0, 0,
111                              0, 0, 0, 0, 0, 1, 0, 0,
112                              0, 0, 0, 0, 0, 0, 1, 0,
113                              0, 0, 0, 0, 0, 0, 0, 1}; //identity
114     float   biasValue[]   = {0, 0, 0, 0, 0, 0, 0, 0};
115 
116     // fully connected operation
117     AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 1, 8});
118     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8}, weightValue);
119     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8}, biasValue);
120     AddIntOperand<HalPolicy>(model, actValue);
121     AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
122 
123     model.operations.resize(1);
124 
125     model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
126     model.operations[0].inputs  = hidl_vec<uint32_t>{0,1,2,3};
127     model.operations[0].outputs = hidl_vec<uint32_t>{4};
128 
129     // make the prepared model
130     android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
131 
132     // construct the request
133     DataLocation inloc = {};
134     inloc.poolIndex = 0;
135     inloc.offset    = 0;
136     inloc.length    = 8 * sizeof(float);
137     RequestArgument input = {};
138     input.location = inloc;
139     input.dimensions = hidl_vec<uint32_t>{};
140 
141     DataLocation outloc = {};
142     outloc.poolIndex = 1;
143     outloc.offset    = 0;
144     outloc.length    = 8 * sizeof(float);
145     RequestArgument output = {};
146     output.location  = outloc;
147     output.dimensions = hidl_vec<uint32_t>{};
148 
149     V1_0::Request request = {};
150     request.inputs  = hidl_vec<RequestArgument>{input};
151     request.outputs = hidl_vec<RequestArgument>{output};
152 
153     // set the input data
154     float indata[] = {1,2,3,4,5,6,7,8};
155     AddPoolAndSetData(8, request, indata);
156 
157     // add memory for the output
158     android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
159     float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
160 
161     // run the execution
162     if (preparedModel != nullptr)
163     {
164         Execute(preparedModel, request);
165     }
166 
167     // check the result
168     BOOST_TEST(outdata[0] == 1);
169     BOOST_TEST(outdata[1] == 2);
170     BOOST_TEST(outdata[2] == 3);
171     BOOST_TEST(outdata[3] == 4);
172     BOOST_TEST(outdata[4] == 5);
173     BOOST_TEST(outdata[5] == 6);
174     BOOST_TEST(outdata[6] == 7);
175     BOOST_TEST(outdata[7] == 8);
176 }
177 
BOOST_AUTO_TEST_CASE(TestFullyConnected4dInputReshape)178 BOOST_AUTO_TEST_CASE(TestFullyConnected4dInputReshape)
179 {
180     auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
181 
182     V1_0::ErrorStatus error;
183     std::vector<bool> sup;
184 
185     ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
186         {
187             error = status;
188             sup = supported;
189         };
190 
191     HalPolicy::Model model = {};
192 
193     // operands
194     int32_t actValue      = 0;
195     float   weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
196                              0, 1, 0, 0, 0, 0, 0, 0,
197                              0, 0, 1, 0, 0, 0, 0, 0,
198                              0, 0, 0, 1, 0, 0, 0, 0,
199                              0, 0, 0, 0, 1, 0, 0, 0,
200                              0, 0, 0, 0, 0, 1, 0, 0,
201                              0, 0, 0, 0, 0, 0, 1, 0,
202                              0, 0, 0, 0, 0, 0, 0, 1}; //identity
203     float   biasValue[]   = {0, 0, 0, 0, 0, 0, 0, 0};
204 
205     // fully connected operation
206     AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 2, 2, 2});
207     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8}, weightValue);
208     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8}, biasValue);
209     AddIntOperand<HalPolicy>(model, actValue);
210     AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
211 
212     model.operations.resize(1);
213 
214     model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
215     model.operations[0].inputs  = hidl_vec<uint32_t>{0,1,2,3};
216     model.operations[0].outputs = hidl_vec<uint32_t>{4};
217 
218     // make the prepared model
219     android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
220 
221     // construct the request
222     DataLocation inloc = {};
223     inloc.poolIndex = 0;
224     inloc.offset    = 0;
225     inloc.length    = 8 * sizeof(float);
226     RequestArgument input = {};
227     input.location = inloc;
228     input.dimensions = hidl_vec<uint32_t>{};
229 
230     DataLocation outloc = {};
231     outloc.poolIndex = 1;
232     outloc.offset    = 0;
233     outloc.length    = 8 * sizeof(float);
234     RequestArgument output = {};
235     output.location  = outloc;
236     output.dimensions = hidl_vec<uint32_t>{};
237 
238     V1_0::Request request = {};
239     request.inputs  = hidl_vec<RequestArgument>{input};
240     request.outputs = hidl_vec<RequestArgument>{output};
241 
242     // set the input data
243     float indata[] = {1,2,3,4,5,6,7,8};
244     AddPoolAndSetData(8, request, indata);
245 
246     // add memory for the output
247     android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
248     float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
249 
250     // run the execution
251     if (preparedModel != nullptr)
252     {
253         Execute(preparedModel, request);
254     }
255 
256     // check the result
257     BOOST_TEST(outdata[0] == 1);
258     BOOST_TEST(outdata[1] == 2);
259     BOOST_TEST(outdata[2] == 3);
260     BOOST_TEST(outdata[3] == 4);
261     BOOST_TEST(outdata[4] == 5);
262     BOOST_TEST(outdata[5] == 6);
263     BOOST_TEST(outdata[6] == 7);
264     BOOST_TEST(outdata[7] == 8);
265 }
266 
267 BOOST_AUTO_TEST_SUITE_END()
268