e9eeba7fa1fb78a6914257f2a57bcf8ec5aacaea
[platform/upstream/dldt.git] / inference-engine / tests / unit / engines / gna / gna_matcher.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <mock_icnn_network.hpp>
6 #include "gna_matcher.hpp"
7 #include <gna/gna_config.hpp>
8 #include <gna-api-types-xnn.h>
9 #include <gna_plugin/gna_executable_network.hpp>
10 #include "gna_plugin.hpp"
11 #include "gna_mock_api.hpp"
12 #include "matchers/precision_matcher.hpp"
13 #include "matchers/pwl_matcher.hpp"
14 #include "matchers/copy_matcher.hpp"
15 #include "matchers/diag_matcher.hpp"
16 #include "matchers/pwl_quantization_metrics_matcher.hpp"
17 #include "matchers/conv_matcher.hpp"
18 #include "matchers/pool_matcher.hpp"
19 #include "matchers/fill_with_data.hpp"
20 #include "matchers/weights_matcher.hpp"
21
22 #include <gmock/gmock-generated-actions.h>
23 #include <gmock/gmock-more-actions.h>
24 #include "gmock/gmock.h"
25 #include "matchers/input_data_matcher.hpp"
26 #include <inference_engine/blob_factory.hpp>
27 #include <details/ie_cnn_network_tools.h>
28
29 using namespace std;
30 using namespace InferenceEngine;
31 using namespace GNAPluginNS;
32 using namespace ::testing;
33
34 class NullAllocator : public IAllocator {
35  void * ptr = nullptr;
36 public:
37     NullAllocator() {
38         ptr = new char[1];
39     }
40     ~NullAllocator() {
41         delete[] static_cast<char*>(ptr);
42     }
43     void * lock(void * handle, LockOp = LOCK_FOR_WRITE)  noexcept override {
44         return ptr;
45     }
46     void  unlock(void * handle) noexcept override {
47
48     }
49     void * alloc(size_t size) noexcept override {
50         return ptr;
51     }
52     virtual bool   free(void* handle) noexcept {
53         return true;
54     }
55     virtual void Release() noexcept {
56         delete this;
57     }
58 };
59
60 std::vector<CNNLayerPtr> TIBodySortTopologically(const TensorIterator::Body &body) {
61     std::vector<CNNLayerPtr> all_layers;
62
63     auto getAllInputs = [&](const std::vector<DataPtr> &heads) {
64         CNNLayerSet inputLayers;
65         std::unordered_set<CNNLayer *> allLayers;
66
67         // Define all start layers
68         for (const auto &data : heads) {
69             auto &secondLayers = data->getInputTo();
70
71             details::UnorderedDFS(allLayers, secondLayers.begin()->second, [&](CNNLayerPtr layer) {
72                 if (layer->insData.empty()) {
73                     inputLayers.insert(layer);
74                 }
75             }, false);
76         }
77
78         std::vector<DataPtr> res = heads;
79         // Add fake input data to point on not achievable
80         // layers from head (like const placeholders)
81         for (auto &starter : inputLayers) {
82             DataPtr holder(new Data(starter->name + ":input_holder", starter->precision));
83             holder->getInputTo()[starter->name] = starter;
84             res.push_back(holder);
85         }
86         return res;
87     };
88
89     auto all_input_layers = getAllInputs(body.inputs);
90     CNNNetForestDFS(all_input_layers, [&](CNNLayerPtr  current){
91         all_layers.push_back(current);
92     }, false);
93     std::reverse(all_layers.begin(), all_layers.end());
94     return all_layers;
95 }
96
97 void GNAPropagateMatcher :: match() {
98     try {
99         // matching gna propagate forward call.
100         GNAPlugin plugin(_env.config);
101         plugin.SetPolicy(_env.policy);
102         size_t inputSize = 10;
103         size_t outputSize = 10;
104         InputsDataMap inputsInfo;
105         OutputsDataMap  outputsInfo;
106
107         auto loadNetworkFromIR = [&] () {
108             CNNNetReader net_reader;
109             ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
110
111             auto weights_fake = make_shared<TBlob<uint8_t>>(Precision::U8, C, SizeVector({std::numeric_limits<uint32_t>::max()}), make_shared<NullAllocator>());
112             net_reader.SetWeights(weights_fake);
113
114             auto net_original = net_reader.getNetwork();
115             auto input_dims = net_original.getInputsInfo().begin()->second->getTensorDesc().getDims();
116             auto output = net_original.getOutputsInfo();
117             // sometimes network might be created without outputs - ex memory output only
118             auto output_dims = !output.empty() ? output.begin()->second->getTensorDesc().getDims() : input_dims;
119
120             inputSize = details::product(std::begin(input_dims), std::end(input_dims));
121             outputSize = details::product(std::begin(output_dims), std::end(output_dims));
122
123             size_t weightsSize = 0;
124             std::vector<std::string> dataBlobs = {
125                     "weights",
126                     "biases",
127                     "custom"
128             };
129
130             std::vector<InferenceEngine::CNNLayerPtr> tiBodies;
131             for (auto &layer : net_original) {
132                 if (layer->type == "TensorIterator") {
133                     auto tiBody = TIBodySortTopologically(std::dynamic_pointer_cast<InferenceEngine::TensorIterator>(layer)->body);
134                     tiBodies.insert(tiBodies.end(), tiBody.begin(), tiBody.end());
135                 }
136             }
137             std::vector<CNNLayerPtr> sortedLayers = details::CNNNetSortTopologically(net_original);
138             sortedLayers.insert(sortedLayers.end(), tiBodies.begin(), tiBodies.end());
139
140             for (auto &layer : sortedLayers) {
141                 for (auto &blobName : dataBlobs) {
142                     auto weights = layer->blobs[blobName];
143                     if (weights) {
144                         weightsSize += weights->byteSize();
145                     }
146                 }
147             }
148
149             auto weights = make_shared_blob<uint8_t >({ Precision::U8, {weightsSize}, Layout::C });
150
151             weights->allocate();
152             if (!_env.weightsFillPattern.empty()) {
153                 GNATest::fillWeights(weights, _env.weightsFillPattern);
154             } else {
155                 GNATest::fillWeights(weights);
156             }
157             net_reader.SetWeights(weights);
158
159             net_reader.getNetwork().setTargetDevice(_env.target_device);
160
161             if (_env.cb) {
162                 auto network = net_reader.getNetwork();
163                 _env.cb(network);
164             }
165
166             plugin.LoadNetwork(net_reader.getNetwork());
167
168             inputsInfo = net_reader.getNetwork().getInputsInfo();
169             outputsInfo = net_reader.getNetwork().getOutputsInfo();
170         };
171
172         auto loadNetworkFromAOT = [&] () {
173             auto sp = plugin.ImportNetwork(_env.importedModelFileName);
174             inputsInfo = plugin.GetInputs();
175             outputsInfo = plugin.GetOutputs();
176         };
177
178         std::map<std::string, Blob::Ptr> input;
179         TBlob<float>::Ptr output;
180         size_t in_N = 1;
181         size_t out_N = in_N;
182         size_t in_C;
183         size_t out_C;
184
185         auto loadNetwork = [&]() {
186             if (!_env.importedModelFileName.empty()) {
187                 ASSERT_NO_FATAL_FAILURE(loadNetworkFromAOT());
188             } else {
189                 ASSERT_NO_FATAL_FAILURE(loadNetworkFromIR());
190             }
191             const int channel_idx = 1;
192             bool haveInputs = !_env.input_init.empty();
193             for (auto && info :inputsInfo) {
194                 decltype(_env.input_init)::iterator it;
195                 auto & inputBlob = input[info.first];
196                 if (haveInputs) {
197                     if (inputsInfo.size() != 1) {
198                         ASSERT_NE(it = _env.input_init.find(info.first), _env.input_init.end());
199                     } else {
200                         ASSERT_NE(0, _env.input_init.size());
201                         it = _env.input_init.begin();
202                     }
203                     in_C = it->second.size();
204                     ASSERT_EQ(in_C, info.second->getTensorDesc().getDims()[channel_idx]);
205                 }
206
207                 inputBlob = make_blob_with_precision({ _env.input_precision, info.second->getTensorDesc().getDims(),
208                     info.second->getLayout() });
209                 inputBlob->allocate();
210                 if (haveInputs) {
211                     if (_env.input_precision == Precision::FP32) {
212                         std::copy_n(it->second.cbegin(), in_N * in_C, inputBlob->buffer().as<float *>());
213                     } else if (_env.input_precision == Precision::U8) {
214                         std::copy_n(it->second.cbegin(), in_N * in_C, inputBlob->buffer().as<uint8_t *>());
215                     } else {
216                         std::logic_error(std::string("Unsupported input precision: ") + _env.input_precision.name());
217                     }
218                 }
219             }
220
221             out_C = _env.matchOutput == true ? _env.expected_output.size() : outputSize;
222             output.reset(new TBlob<float>({ Precision::FP32, {out_N, out_C}, Layout::NC }));
223             output->allocate();
224         };
225
226
227         StrictMock<GNACppApi> mockApi;
228         std::vector<uint8_t> data;
229
230         if (_env.target_device == InferenceEngine::TargetDevice::eGNA &&
231                                                          !_env.matchThrows) {
232
233             EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(Invoke([&data](
234                 intel_gna_handle_t nGNADevice,   // handle to GNA accelerator
235                 uint32_t           sizeRequested,
236                 uint32_t*          sizeGranted
237             ) {
238                 data.resize(sizeRequested);
239                 *sizeGranted = sizeRequested;
240                 return &data.front();
241             }));
242             EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
243
244             if(_env.is_profiling_enabled == false) {
245                 EXPECT_CALL(mockApi, GNAWait(_, _, _)).WillOnce(Return(GNA_NOERROR));
246             } else {
247                 EXPECT_CALL(mockApi, GNAWaitPerfRes(_, _, _, _)).WillOnce(Return(GNA_NOERROR));
248             }
249
250             if(_env.is_setup_of_omp_theads_expected == true) {
251                 EXPECT_CALL(mockApi, gmmSetThreads(_)).Times(1);
252             } else {
253                 EXPECT_CALL(mockApi, gmmSetThreads(_)).Times(0);
254             }
255
256             std::unique_ptr<NNetComponentMatcher> combined(new NNetComponentMatcher());
257
258             for (auto & matchWhat : _env.whatToMatch) {
259                 switch(matchWhat) {
260                     case GnaPluginTestEnvironment::matchPrecision :
261                         combined->add(new NNetPrecisionMatcher(_env.nnet_precision, INTEL_AFFINE));
262                         break;
263                     case GnaPluginTestEnvironment::matchProcType :
264                         EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, Eq(_env.proc_type)))
265                             .WillOnce(Return(GNA_NOERROR));
266                         break;
267                     case GnaPluginTestEnvironment::matchPwlInserted :
268                         combined->add(new PWLMatcher(_env.matchInserted, _env.matchQuantity, _env.pwlsToMatchWith));
269                         break;
270                     case GnaPluginTestEnvironment::matchConvInserted:
271                         combined->add(new ConvoluionLayerMatcher(_env.matchInserted, _env.matchQuantity));
272                         break;
273                     case GnaPluginTestEnvironment::matchMaxPoolingInserted:
274                         combined->add(new PoolingLayerMatcher(_env.matchInserted, _env.matchQuantity, true));
275                         break;
276                     case GnaPluginTestEnvironment::matchPwlQuantizeMetrics :
277                         combined->add(new PWLQuantizationMetricsMatcher(_env.type,
278                                                                         _env.quantization_presicion_threshold,
279                                                                         _env.quantization_segments_threshold));
280                         break;
281                     case GnaPluginTestEnvironment::matchCopyInserted :
282                         combined->add(new CopyLayerMatcher(_env.matchInserted, _env.matchQuantity));
283                         break;
284                     case GnaPluginTestEnvironment::matchDiagonalInserted :
285                         combined->add(new DiagLayerMatcher(_env.matchInserted, _env.matchQuantity));
286                         break;
287                     case GnaPluginTestEnvironment::saveArgs :
288                         EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, _))
289                             .WillOnce(DoAll(SaveArgPointee<1>(savedNet), Return(GNA_NOERROR)));
290                         break;
291                     case GnaPluginTestEnvironment::matchInputData :
292                         combined->add(new InputDataMatcher(_env.input_processed));
293                         break;
294                     case GnaPluginTestEnvironment::fillOutputValues :
295                         combined->add(new OutputFiller(_env.fillValue, _env.fillValue));
296                         break;
297                     case GnaPluginTestEnvironment::matchAffineWeightsTranspose:
298                         HasWeightsTranspozed(combined, _env.transposedData, _env.transposeArgs);
299                         break;
300                     case GnaPluginTestEnvironment::matchAffineWeights:
301                         HasWeightsEq(combined, _env.transposedData);
302                         break;
303                     case GnaPluginTestEnvironment::saveAffineWeights:
304                         SaveWeights(combined, _env.transposedData, _env.transposedArgsForSaving);
305                         break;
306                     default:
307                         EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, _))
308                             .WillOnce(Return(GNA_NOERROR));
309                         break;
310                 }
311             }
312             if (combined && !combined->empty()) {
313                 EXPECT_CALL(mockApi, GNAPropagateForward(_, ::testing::MakeMatcher(combined.release()), _, _, _,_)).WillOnce(Return(GNA_NOERROR));
314             }
315         }
316
317         loadNetwork();
318
319         if (!inputsInfo.empty()) {
320             BlobMap  input_blob_map;
321             BlobMap  output_blob_map;
322             for (auto info : inputsInfo) {
323                 size_t current_size = InferenceEngine::details::product(info.second->getTensorDesc().getDims());
324                 input_blob_map[info.first] = input[info.first];
325             }
326             size_t offset = 0;
327             for (auto info : outputsInfo) {
328                 size_t current_size = InferenceEngine::details::product(info.second->getTensorDesc().getDims());
329                 output_blob_map[info.first] = make_shared_blob<float>(
330                     { info.second->getPrecision(),
331                     {1, details::product(info.second->getTensorDesc().getDims())}, NC },
332                     output->data() + offset, current_size * sizeof(float));
333                 offset += current_size;
334             }
335
336             plugin.Infer(input_blob_map, output_blob_map);
337
338         } else {
339             plugin.Infer(*input.begin()->second, *output);
340         }
341
342
343         if (_env.matchOutput) {
344             std::vector<float> actual_output(output->size());
345
346             std::copy_n(output->cbuffer().as<float *>(), out_C * out_N, actual_output.begin());
347
348             for (auto ref = _env.expected_output.begin(); ref != _env.expected_output.end(); ref++ ) {
349                 auto idx = std::distance( _env.expected_output.begin(), ref);
350                 ASSERT_FLOAT_EQ(*ref, actual_output[idx]) << "at "<< idx;
351             }
352         }
353
354         std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> perfMap;
355         plugin.GetPerformanceCounts(perfMap);
356
357         if(_env.is_profiling_enabled != false) {
358             ASSERT_NE(perfMap.empty(),true);
359         } else {
360             ASSERT_NE(perfMap.empty(),false);
361         }
362
363     }
364     catch(std::exception &ex) {
365         if (!_env.matchThrows) {
366             FAIL() << ex.what();
367         }
368     }
369     catch(...) {
370         if (!_env.matchThrows) {
371             FAIL() << "unknown exception thrown";
372         }
373     }
374
375 }
376
377 void GNAPluginCreationMatcher :: match() {
378     if (_env.matchThrows) {
379         ASSERT_ANY_THROW(GNAPlugin(_env.config));
380         return;
381     }
382     GNAPlugin(_env.config);
383 }
384
385
386 void GNAPluginAOTMatcher :: match() {
387     // matching gna_propagate forward call.
388     MockICNNNetwork net;
389     CNNNetReader net_reader;
390     ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
391
392     size_t weightsSize = 440*3;
393
394     auto weights = make_shared_blob<uint8_t >({ Precision::U8, {weightsSize}, Layout::C });
395     weights->allocate();
396     GNATest::fillWeights(weights);
397     net_reader.SetWeights(weights);
398
399     GNAPlugin plugin(_env.config);
400
401     TBlob<float> input({ Precision::FP32, {1, 10}, Layout::NC });
402     input.allocate();
403
404
405     TBlob<float> output({ Precision::FP32, {1, 10}, Layout::NC });
406     output.allocate();
407
408     net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
409
410     if (_env.cb) {
411         auto network = net_reader.getNetwork();
412         _env.cb(network);
413     }
414
415     GNACppApi mockApi;
416     std::vector<uint8_t> data(10000);
417     EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
418     EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
419
420     plugin.LoadNetwork(net_reader.getNetwork());
421     plugin.Export(_env.exportedModelFileName);
422 }
423
424
425 void GNADumpXNNMatcher::load(GNAPlugin & plugin) {
426
427     // matching gna DumpXNN forward call.
428     plugin = GNAPlugin(_env.config);
429
430     auto loadNetworkFromIR = [&]() {
431         MockICNNNetwork net;
432         CNNNetReader net_reader;
433         ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
434
435         size_t weightsSize = 440 * 3;
436
437         auto weights = make_shared_blob<uint8_t>({ Precision::U8, {weightsSize}, Layout::C });
438         weights->allocate();
439         GNATest::fillWeights(weights);
440         net_reader.SetWeights(weights);
441
442         net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
443
444         if (_env.cb) {
445             auto network = net_reader.getNetwork();
446             _env.cb(network);
447         }
448
449         plugin.LoadNetwork(net_reader.getNetwork());
450     };
451
452     auto loadNetworkFromAOT = [&]() {
453         plugin.ImportNetwork(_env.importedModelFileName);
454     };
455
456     auto loadNetwork = [&]() {
457         if (!_env.importedModelFileName.empty()) {
458             loadNetworkFromAOT();
459         } else {
460             loadNetworkFromIR();
461         }
462     };
463
464     loadNetwork();
465 }
466
467 void GNADumpXNNMatcher::match() {
468
469     GNACppApi mockApi;
470     std::vector<uint8_t> data(10000);
471     if (!_env.matchThrows) {
472
473         EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
474         EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
475         intel_gna_model_header header = {};
476         header.model_size = 1;
477         EXPECT_CALL(mockApi, GNADumpXnn(_, _, _, _, _,_)).WillOnce(DoAll(SetArgPointee<3>(header), Return((void*)::operator new(1))));
478         EXPECT_CALL(mockApi, GNAFree(_)).WillOnce(Return(GNA_NOERROR));
479         EXPECT_CALL(mockApi, GNADeviceClose(_)).WillOnce(Return(GNA_NOERROR));
480     }
481
482     try {
483         // matching gna DumpXNN forward call.
484         GNAPluginNS::GNAPlugin plugin;
485         load(plugin);
486     }
487     catch(std::exception &ex) {
488         if (!_env.matchThrows) {
489             FAIL() << ex.what();
490         }
491     }
492     catch(...) {
493         if (!_env.matchThrows) {
494             FAIL() << "unknown exception thrown";
495         }
496     }
497
498 }
499
500 void GNAQueryStateMatcher :: match() {
501
502    //  TODO : avoid copy pastes
503     GNACppApi mockApi;
504     std::vector<uint8_t> data(10000);
505
506     std::shared_ptr<IExecutableNetworkInternal> executer;
507     auto loadNetworkFromIR = [&]() {
508         MockICNNNetwork net;
509         CNNNetReader net_reader;
510         ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
511
512         size_t weightsSize = 440 * 3;
513
514         auto weights = make_shared_blob<uint8_t>({ Precision::U8, {weightsSize}, Layout::C });
515         weights->allocate();
516         GNATest::fillWeights(weights);
517         net_reader.SetWeights(weights);
518
519         net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
520
521         if (_env.cb) {
522             auto network = net_reader.getNetwork();
523             _env.cb(network);
524         }
525
526         executer.reset(new GNAExecutableNetwork(net_reader.getNetwork(), _env.config));
527     };
528
529     auto loadNetworkFromAOT = [&]() {
530         executer.reset(new GNAExecutableNetwork(_env.importedModelFileName, _env.config));
531     };
532
533     auto loadNetwork = [&]() {
534         if (!_env.importedModelFileName.empty()) {
535             return loadNetworkFromAOT();
536         } else {
537             return loadNetworkFromIR();
538         }
539     };
540
541
542     EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
543     EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
544     EXPECT_CALL(mockApi, GNAFree(_)).WillOnce(Return(GNA_NOERROR));
545     EXPECT_CALL(mockApi, GNADeviceClose(_)).WillOnce(Return(GNA_NOERROR));
546
547     try {
548         loadNetwork();
549         if (GnaPluginTestEnvironment::kAnyNotNull == _env.numberOfStates) {
550             auto states = executer->QueryState();
551             ASSERT_NE(states.size(), 0);
552             // usually states are callable
553             for (auto & state : states) {
554                 state->Reset();
555             }
556         } else if (_env.numberOfStates >= 0) {
557             ASSERT_EQ(executer->QueryState().size(), _env.numberOfStates);
558         } else {
559             FAIL() << "number of memory states expectation not set";
560         }
561
562     }
563     catch(std::exception &ex) {
564         FAIL() << ex.what();
565     }
566     catch(...) {
567         FAIL() << "unknown exception thrown";
568     }
569 }